Trabajo elaborado para la asignatura “Programación y manejo de datos en la era del Big Data” de la Universitat de València durante el curso 2021-2022. El repo del trabajo está aquí.

La página web de la asignatura y los trabajos de mis compañeros pueden verse aquí.


1. Introducción

La Formula 1 es uno de los deportes/espectaculos más importantes del mundo, logrando a lo largo de sus historia captar a millones y millones de espectadores. Nuetro trabajo pretende plasmar la grandeza de la Fórmula 1 a través de distintos datos que pueden verse a contimnuación, tanto presentes como pasados. Además, parte del trabajo se ha centrado en la figura de Fernando Alonso, el piloto con mayor importancia en España, y uno de los más relevantes en la historia de la Formula 1.
En relación con la asignatura, la elección del tema se debe a lo fundamental que son los datos en este deporte, tanto para la elaboración de estrategias, el diseño de los coches o incluso de las pistas. Debido a todas estas razones, creemos que la F1, a pesar de no ser un tema relacionado con la economía, encaja perfectamente con la asignatura.

THE PLAN

2. Datos

Hemos encontrado en kaggle bastantes conjuntos de datos con los que poder trabajar, pero especialmente este, que posee gran variedad de datos en lo referente a pilotos, resultados, circuitos, tiempos, etc.

2.1. Procesando los datos

A continuación se muestra toda la manipulación de los datos, a partir del conjunto de datos mostrado anteriormente, y que posteriormente son utilizados para la realización de los distintas partes que forman el trabajo.

#---PREPARACION DE LOS DATOS
tiempos <- rio::import(file = "./datos/lap_times.csv")
pilotos <- rio::import(file = "./datos/drivers.csv")
resultados <- rio::import(file = "./datos/results.csv")
carreras <- rio::import(file = "./datos/races.csv")
escuderias <- rio::import(file = "./datos/constructors.csv")
escuderias2 <- rio::import(file = "./datos/constructor_standings.csv")
result_escuderias <- rio::import(file = "./datos/constructor_results.csv")
circuitos <- rio::import(file = "./datos/circuits.csv")

#----------------------------------------
#capitulo oscuro del deporte
#creo df de muertes de formula 1
muertesf1 <- data.frame(
  "orden" = 1:42,
  "driverRef" = c("Chet Miller", "Carl Scaraborough", "Onofre Marimon", "Manny Ayulo", "Bill Vukovich", "Alberto Ascari","Eugenio Castellotti", "Keith Andrews", "Pat O'Connor", "Luigi Musso", "Peter Collins", "Stuart Lewis-Evans", "Jerry Unser", "Bob Cortner", "Ivor Bueb", "Chris Bristow", "Alan Stacey", "Giulio Cabianca", "Wolfgang von Trips", "Carel Godin de Beaufort", "John Taylor", "Lorenzo Bandini", "Bob Anderson", "Jo Schlesser", "Gerhard Mitter", "Piers Courage", "Jochen Rindt", "Jo Siffert", "Roger Williamson", "François Cevert", "Peter Revson", "Helmuth Koinigg", "Mark Donohue", "Tom Pryce", "Ronnie Peterson", "Patrick Depailler", "Gilles Villeneuve", "Riccardo Paletti", "Elio de Angelis", "Roland Ratzenberger", "Ayrton Senna", "Jules Bianchi"),
  "nationality" = c("American", "American", "Argentine", "American", "American", "Italian","Italian", "American", "American", "Italian", "British", "British", "American", "American", "British", "British", "British", "Italian", "German", "Dutch", "British", "Italian" , "British", "French", "German", "British", "Austrian", "Swiss", "British", "French", "American", "Austrian", "American", "British", "Swedish", "French", "Canadian", "Italian", "Italian", "Austrian", "Brazilian", "French"),
  "fecha_muerte" = c(1953, 1953, 1954, 1955, 1955, 1955, 1957, 1957, 1958,1958,1958,1958,1959,1959,1959,1960, 1960,1961,1961,1964,1966, 1967, 1967,1968,1969, 1970,1970,1971,1973,1973,1974,1974,1975,1977,1978,1980,1982,1982,1986,1994,1994,2014))
#no pongo las comillas en los años para que se creen directamente como observaciones numericas

#creo un df con todos los años para luego fusionarlo, ya que no hay muertes todos los años 
anyos <- data.frame(
  "orden" = 1:71,
  "año" = c(1950:2020))

#sumatorio de las muertes por año
muertes_anyo <- muertesf1 %>% group_by(fecha_muerte) %>% mutate(muertesxanyo = sum(n())) %>% distinct(fecha_muerte, muertesxanyo) 

#fusiono los 2 dfs para que tenga en cuenta los años donde no hay muertes
muertesf1_final <- full_join(muertes_anyo, anyos, c("fecha_muerte" = "año")) %>% select(fecha_muerte,muertesxanyo) %>% arrange(fecha_muerte)

#convierto los N/A en 0, es decir, cuando no hay observaciones, ha habido 0 muertes
muertesf1_final[is.na(muertesf1_final)] <- 0

#------------------------------------------------
#str(resultados)
#str(pilotos)
#pilotos[, c(1)] <- sapply(pilotos[, c(1)], as.numeric)
#resultados[, c(3,6,9)] <- sapply(resultados[, c(3,6,9)], as.numeric)

#----------------------------------------------------------------------------------

#numero de carreras que ha corrido cada piloto

n_carreras <- resultados %>% group_by(driverId) %>% mutate(numero_carreras = sum(n())) %>% distinct(numero_carreras) %>% arrange(desc(numero_carreras)) 

n_carreras_nom <- full_join(n_carreras, pilotos, c ("driverId" = "driverId")) %>% select(driverId, driverRef, numero_carreras)  %>%  filter(numero_carreras >= 202 ) #los 20 qque mas carreras tienen (no funciona usar slice_max)

#--------------------------------------------------------------------------------
#nacionalidad de los pilotos a lo largo de la historia 
#mapa
nacionalidad <- pilotos %>% group_by(nationality) %>% mutate(numero_compatriotas = sum(n())) %>% distinct(numero_compatriotas) %>% arrange(desc(numero_compatriotas)) %>% 
  str_replace_all(., "British", "United Kingdom") %>% 
  str_replace_all(., "American", "United States") %>% 
  str_replace_all(., "Italian", 'Italy') %>% 
  str_replace_all(., "French" , 'France') %>% 
  str_replace_all(., "German" , 'Germany') %>% 
  str_replace_all(., "Brazilian" , 'Brazil') %>% 
  str_replace_all(., "Argentine" , 'Argentina') %>% 
  str_replace_all(., "Swiss" , 'Switzerland') %>% 
  str_replace_all(., "Belgian" , 'Belgium') %>% 
  str_replace_all(., "South African" , 'South Africa') %>% 
  str_replace_all(., "Japanese" , 'Japan') %>% 
  str_replace_all(., "Australian" , 'Australia') %>%
  str_replace_all(., "Dutch" , 'Netherlands') %>%
  str_replace_all(., "Spanish" , 'Spain') %>%
  str_replace_all(., "Austrian" , 'Austria') %>%
  str_replace_all(., "Canadian" , 'Canada') %>%
  str_replace_all(., "Swedish" , 'Sweden') %>%
  str_replace_all(., "Finnish" , 'Finland') %>%
  str_replace_all(., "New Zealander" , 'New Zealand') %>%
  str_replace_all(., "Mexican" , 'Mexico') %>%
  str_replace_all(., "Irish" , 'Ireland') %>%
  str_replace_all(., "Danish" , 'Denmark') %>%
  str_replace_all(., "Portuguese" , 'Portugal') %>%
  str_replace_all(., "Monegasque" , 'France') %>%
  str_replace_all(., "Rhodesian" , 'Zimbabwe') %>%
  str_replace_all(., "Uruguayan" , 'Uruguay') %>%
  str_replace_all(., "Russian" , 'Russia') %>%
  str_replace_all(., "Colombian" , 'Colombia') %>%
  str_replace_all(., "Venezuelan" , 'Venezuela') %>%
  str_replace_all(., "East German" , 'German') %>%
  str_replace_all(., "Indian" , 'India') %>%
  str_replace_all(., "Thai" , 'Thailand') %>%
  str_replace_all(., "Polish" , 'Poland') %>%
  str_replace_all(., "Monegasque" , 'France') %>%
  str_replace_all(., "Hungarian" , 'Hungary') %>%
  str_replace_all(., "Czech" , 'Czech Rep.') %>%
  str_replace_all(., "Malaysian" , 'Malaysia') %>%
  str_replace_all(., "Chilean" , 'Chile') %>%
  str_replace_all(., "Liechtensteiner" , 'Switzerland') %>%
  str_replace_all(., "American-Italian" , 'United States') %>%
  str_replace_all(., "Argentine-Italian" , 'Argentina') %>%
  str_replace_all(., "Indonesian" , 'Indonesia')

paises_normales <- c("United Kingdom", "United States", "Italy", "France", "Germany", "Brazil", "Argentina", "Switzerland", "Belgium", "South Africa", "Japan", "Australia", "Netherlands", "Spain", "Austria", "Canada", "Sweden", "Finland", "New Zealand", "Mexico", "Ireland", "Denmark", "Portugal", "France", "Zimbabwe", "Uruguay", "Russia", "Colombia", "Venezuela", "Germany", "India", "Thailand", "Poland", "Hungary", "Czech Rep.", "Malaysia", "Chile", "Switzerland", "United States", "Argentina", "Indonesia" )

nacionalidad <- pilotos %>% group_by(nationality) %>% 
  mutate(numero_compatriotas = sum(n())) %>% 
  distinct(numero_compatriotas) %>% 
  arrange(desc(numero_compatriotas)) %>% 
  add_column(paises_normales) %>%  
  group_by(paises_normales) %>% 
  mutate(total_pilotos = sum(numero_compatriotas)) %>%  
  distinct(paises_normales, total_pilotos)

data(World)
world <- World; rm(World)

world <- world[!(world$name %in% c('Greenland', 'Antarctica')),]

pilotos_por_paises <- full_join(nacionalidad, world, c( "paises_normales" = "name")) 

pilotos_por_paises$country <- NULL

pilotos_por_paises[is.na(pilotos_por_paises)] <- 0

gg_pilotos_por_paises <- ggplot(data = pilotos_por_paises, aes(geometry = geometry)) + geom_sf() +
       labs(title = "Pilotos por país",
            caption = "Menor intensidad de color en aquellos paises con más pilotos")

gg_pilotos_por_paises <- gg_pilotos_por_paises + 
  geom_sf(aes(fill = total_pilotos)) + 
  theme(plot.subtitle = element_text(colour = "white"),
    plot.caption = element_text(colour = "white"),
    axis.ticks = element_line(linetype = "blank"),
    panel.grid.major = element_line(linetype = "blank"),
    panel.grid.minor = element_line(linetype = "blank"),
    axis.text = element_text(colour = "gray13"),
    plot.title = element_text(size = 20,
        colour = "white", hjust = 0.5), legend.text = element_text(colour = "white"),
    legend.title = element_text(colour = "white"),
    panel.background = element_rect(fill = "gray13"),
    plot.background = element_rect(fill = "gray13"),
    legend.background = element_rect(fill = "gray13")) +labs(fill = "Nª de pilotos") + theme(panel.background = element_rect(colour = "gray13"),
    plot.background = element_rect(colour = "gray13")) + theme(panel.grid.major = element_line(colour = NA),
    panel.background = element_rect(linetype = "solid"),
    plot.background = element_rect(linetype = "solid")) + scale_fill_gradient2(low = "white", mid = "pink", high = "red", midpoint = .02)

#------------------------------------------------------------------------------
# numero de victorias por piloto
victorias <- resultados %>% filter(position == "1") %>% 
  group_by(driverId) %>% 
  mutate(n_victorias = sum(n())) %>% 
  distinct(n_victorias) %>% 
  arrange(desc(n_victorias))

#aqui fusiono con el df de pilotos para que aparezca el nombre y no sólo el ID del piloto en cuestion, y hago lo mismo que en el apartado de arriba para ordenar
victorias_con_nombre <- full_join(victorias, pilotos, c ("driverId" = "driverId")) %>% 
  select(driverId, nationality, driverRef, n_victorias)  
mas_victorias <- victorias_con_nombre %>%  filter(n_victorias >= 25 ) 

#victorias 2
victorias2 <- full_join(pilotos, resultados, c("driverId" = "driverId")) %>% 
  full_join(., carreras, c("raceId" = "raceId")) %>% 
  select(driverId, driverRef, position, year, date) %>% 
  filter(position == 1) %>% 
  group_by(driverRef) %>% 
  mutate(victoria_num = sum( NN = n())) %>% 
  filter(victoria_num >= 20) %>% 
  arrange(victoria_num, date) %>% 
  mutate( suma_vic = cumsum(position))

#-------------------------------------------------

#resultado medio

resultados[, c(7)] <- sapply(resultados[, c(7)], as.numeric)
resultados[is.na(resultados)] <- 25 

#resultado_medio <-  full_join(pilotos, resultados,  c ("driverId" = "driverId")) %>% 
#select(driverId, driverRef, position) %>% 
 # group_by(driverId) %>% 
  #mutate(result_medio = mean(position)) %>% 
  #distinct (driverId, driverRef, result_medio) %>% arrange(result_medio)

#resultado medio en clasificacion
resultado_medio_clas <-  full_join(pilotos, resultados,  c ("driverId" = "driverId")) %>% 
  select(driverId, driverRef, grid) %>% 
  group_by(driverId) %>% 
  mutate(result_medio_clas = mean(grid)) %>% 
  distinct (driverId, driverRef, result_medio_clas)  %>% 
  filter(result_medio_clas > 0) %>% 
  arrange(result_medio_clas)  


#numero de vueltas liderando


#puntos por carrera (puntos/carrera)

puntos_x_carrera <-  full_join(pilotos, resultados,  c ("driverId" = "driverId")) %>% select(driverId, driverRef, points) %>% full_join(., n_carreras,  c ("driverId" = "driverId")) %>% group_by(driverId) %>% mutate(total_puntos = sum(points)) %>% distinct(driverId, driverRef, numero_carreras, total_puntos) %>% mutate(media_puntos = total_puntos/numero_carreras) %>% arrange(desc(media_puntos))

#-------------------------------
#remontadas

#mas posiciones remontadas en una carrera gran premio


resultados[, c(6,9)] <- sapply(resultados[, c(6,9)], as.numeric) #transformo variables grid y positionOrder en numerico
str(resultados) # para comprobarlo
#> 'data.frame':    25140 obs. of  18 variables:
#>  $ resultId       : int  1 2 3 4 5 6 7 8 9 10 ...
#>  $ raceId         : int  18 18 18 18 18 18 18 18 18 18 ...
#>  $ driverId       : int  1 2 3 4 5 6 7 8 9 10 ...
#>  $ constructorId  : int  1 2 3 4 1 3 5 6 2 7 ...
#>  $ number         : chr  "22" "3" "7" "5" ...
#>  $ grid           : num  1 5 7 11 3 13 17 15 2 18 ...
#>  $ position       : num  1 2 3 4 5 6 7 8 25 25 ...
#>  $ positionText   : chr  "1" "2" "3" "4" ...
#>  $ positionOrder  : num  1 2 3 4 5 6 7 8 9 10 ...
#>  $ points         : num  10 8 6 5 4 3 2 1 0 0 ...
#>  $ laps           : int  58 58 58 58 58 57 55 53 47 43 ...
#>  $ time           : chr  "1:34:50.616" "+5.478" "+8.163" "+17.181" ...
#>  $ milliseconds   : chr  "5690616" "5696094" "5698779" "5707797" ...
#>  $ fastestLap     : chr  "39" "41" "41" "58" ...
#>  $ rank           : chr  "2" "3" "5" "7" ...
#>  $ fastestLapTime : chr  "1:27.452" "1:27.739" "1:28.090" "1:28.603" ...
#>  $ fastestLapSpeed: chr  "218.300" "217.586" "216.719" "215.464" ...
#>  $ statusId       : int  1 1 1 1 1 11 5 5 4 3 ...
#mayores remontadas de la historia, se resta posicion de salida - posicion final
puestos_remontados <- resultados %>% mutate(remontados = grid - positionOrder) %>% 
  select(raceId, driverId, grid, positionOrder, remontados) 


#de toda la historia
circuitos_gp <- full_join(carreras, circuitos, c("circuitId" = "circuitId")) %>% 
  select(circuitId, name.y, raceId, year)

ptos_remont_carrera <- inner_join(puestos_remontados, circuitos_gp)

puestos_remont_piloto <- full_join(pilotos, ptos_remont_carrera, c("driverId" = "driverId")) %>% 
  slice_max(remontados, n=10) %>% 
  select(driverId, driverRef,name.y,year, raceId, grid, positionOrder, remontados)

# de la hisotoria reciente
circuitos_gp_recient <- full_join(carreras, circuitos, c("circuitId" = "circuitId")) %>% 
  select(circuitId, name.y, raceId, year) %>% 
  filter(year >= 1995)

ptos_remont_carrera_recient <- inner_join(puestos_remontados, circuitos_gp_recient)

puestos_remont_piloto_recient <- full_join(pilotos, ptos_remont_carrera_recient, c("driverId" = "driverId")) %>% 
  slice_max(remontados, n=10) %>% 
  select(driverId, driverRef, name.y, year,raceId, grid, positionOrder, remontados) %>% 
  slice(1:4,6:8,10) %>% 
  arrange(desc(remontados))


#--------------------------------
#mundiales por naionalidad y piloto
campeones <- full_join(pilotos, resultados, c("driverId" = "driverId")) %>% 
  full_join(., carreras, c("raceId" = "raceId")) %>% 
  select(driverId, driverRef, nationality, constructorId, points, year, round) %>% 
  full_join(., escuderias, c("constructorId" = "constructorId")) %>% 
  select(driverId, driverRef, nationality.x, constructorId, points, year, name, round) %>%  
  group_by(year, driverRef) %>%  
  mutate(puntos_totales = cumsum(points)) %>% 
  ungroup() %>% 
  group_by(year) %>% 
  slice_max(puntos_totales, n=1) %>% 
  ungroup() %>% group_by(driverRef) %>% 
  mutate(total_campeonatos = sum(NN = n())) %>% 
  distinct(driverRef, nationality.x, total_campeonatos) %>% 
  arrange(nationality.x, total_campeonatos)

#----------------------------------
#temporada 2021 tabla

pilotos_2021 <- full_join(carreras, resultados, c("raceId" = "raceId") ) %>% 
  full_join(.,pilotos, c("driverId"="driverId")) %>% 
  filter(year=="2021") %>% 
  select(forename,surname, year) %>% 
  distinct(forename,surname) %>% 
  na.omit() %>% 
  arrange(surname) %>% 
  str_replace_all(., "é", "é") %>% 
  str_replace_all(., "ä", "ä") %>% 
  str_replace_all(., "ö", "ö")

nombres_normales <- c("Alonso", "Bottas", "Gasly", "Giovinazzi", "Hamilton", "Latifi", "Leclerc", "Mazepin", "Norris", "Ocon", "Pérez", "Räikkönen", "Ricciardo", "Russell", "Sainz", "Schumacher", "Stroll", "Tsunoda", "Verstappen", "Vettel")

pilotos_2021 <-  full_join(carreras, resultados, c("raceId" = "raceId") ) %>% 
  full_join(.,pilotos, c("driverId"="driverId")) %>% 
  filter(year=="2021") %>% 
  select(forename,surname, year) %>% 
  distinct(forename,surname) %>% 
  na.omit() %>% 
  arrange(surname) %>% 
  add_column(nombres_normales) 

#--------------------------
#temporada 2021 templos

carreras_21 <- full_join(carreras,circuitos, c("circuitId" = "circuitId")) %>%
  filter(year=="2021") %>%
  select(round, name.x, name.y, date, location,country, lat, lng, alt) %>%
  arrange(round) %>% 
  mutate(round2 = round) 

carreras_21_v2 <- carreras_21[, c(1, 4, 10, 2, 3, 5, 6, 7, 8, 9)]
carreras_21_v2 <- carreras_21_v2%>%  unite(. ,variables, c(1, 5, 7), sep = "; ")


#----------------------------------
#el nano contra todos


alovsall <- full_join(pilotos, resultados, c ("driverId" = "driverId")) %>%  
  select(driverRef, resultId, raceId, constructorId, position, points) %>% 
  full_join(., escuderias, c ("constructorId" = "constructorId")) %>% 
  select(driverRef, resultId, raceId, constructorId, position, position, points, name) %>% 
  full_join(., carreras, c ("raceId" = "raceId")) %>% 
  select(driverRef, resultId, raceId, constructorId, position, position, points, name.x, year, round)

#alo_vs_marques <- alovsall %>% filter(year == 2001, driverRef %in% c("alonso", "marques"), round <= 14)

alo_vs_trulli <- alovsall %>% filter(year %in% c(2003, 2004), driverRef %in% c("alonso", "trulli")) %>% slice(1:15, 17:67) %>% group_by(driverRef, year) %>% mutate(puntos_acumulados = cumsum(points)) %>% ungroup()

alo_vs_fisichella <- alovsall %>% filter(year %in% c(2005, 2006), driverRef %in% c("alonso", "fisichella"))  %>% group_by(driverRef, year) %>% mutate(puntos_acumulados = cumsum(points)) %>% ungroup()

alo_vs_hamilton <- alovsall %>% filter(year %in% c(2007) ,driverRef %in% c("alonso", "hamilton"))  %>% group_by(driverRef, year) %>% mutate(puntos_acumulados = cumsum(points)) %>% ungroup()

alo_vs_piquet <- alovsall %>% filter(year %in% c(2008, 2009), driverRef %in% c("alonso", "piquet_jr")) %>% slice(1:28, 36:63) %>% group_by(driverRef, year) %>% mutate(puntos_acumulados = cumsum(points)) %>% ungroup()

#alo_vs_grosjean <- alovsall %>% filter(year == 2009, driverRef %in% c("alonso", "grosjean"), round >= 11)

alo_vs_massa <- alovsall %>% filter(year %in% c(2010, 2011, 2013), driverRef %in% c("alonso", "massa")) %>% group_by(driverRef, year) %>% mutate(puntos_acumulados = cumsum(points)) %>% ungroup()

alo_vs_raikkonen <- alovsall %>% filter(year == 2014, driverRef %in% c("alonso", "raikkonen")) %>% group_by(driverRef, year) %>% mutate(puntos_acumulados = cumsum(points)) %>% ungroup()

alo_vs_button <- alovsall %>% filter(year %in% c(2015, 2016), driverRef %in% c("alonso", "button")) %>% group_by(driverRef, year) %>% mutate(puntos_acumulados = cumsum(points)) %>% ungroup()

alo_vs_vandoorne <- alovsall %>% filter(year %in% c(2017, 2018), driverRef %in% c("alonso", "vandoorne")) %>% slice(1:45, 47:81) %>% group_by(driverRef, year) %>% mutate(puntos_acumulados = cumsum(points))%>% ungroup() 

alo_vs_ocon <- alovsall %>% filter(year == 2021, driverRef %in% c("alonso", "ocon")) %>% group_by(driverRef, year) %>% mutate(puntos_acumulados = cumsum(points)) %>% ungroup()

ALO_VS_ALL <- full_join(alo_vs_trulli, alo_vs_fisichella, c("driverRef"= "driverRef", "resultId" = "resultId", "raceId" = "raceId", "constructorId" = "constructorId", "position" = "position", "points" = "points", "name.x" = "name.x", "year" = "year", "round" = "round" , "puntos_acumulados" = "puntos_acumulados")) %>% 
  full_join(., alo_vs_hamilton, c("driverRef"= "driverRef", "resultId" = "resultId", "raceId" = "raceId", "constructorId" = "constructorId", "position" = "position", "points" = "points", "name.x" = "name.x", "year" = "year", "round" = "round", "puntos_acumulados" = "puntos_acumulados")) %>% 
  full_join(., alo_vs_piquet, c("driverRef"= "driverRef", "resultId" = "resultId", "raceId" = "raceId", "constructorId" = "constructorId", "position" = "position", "points" = "points", "name.x" = "name.x", "year" = "year", "round" = "round", "puntos_acumulados" = "puntos_acumulados")) %>% 
  full_join(., alo_vs_massa, c("driverRef"= "driverRef", "resultId" = "resultId", "raceId" = "raceId", "constructorId" = "constructorId", "position" = "position", "points" = "points", "name.x" = "name.x", "year" = "year", "round" = "round", "puntos_acumulados" = "puntos_acumulados"))  %>% 
  full_join(., alo_vs_raikkonen, c("driverRef"= "driverRef", "resultId" = "resultId", "raceId" = "raceId", "constructorId" = "constructorId", "position" = "position", "points" = "points", "name.x" = "name.x", "year" = "year", "round" = "round", "puntos_acumulados" = "puntos_acumulados")) %>% 
  full_join(., alo_vs_button, c("driverRef"= "driverRef", "resultId" = "resultId", "raceId" = "raceId", "constructorId" = "constructorId", "position" = "position", "points" = "points", "name.x" = "name.x", "year" = "year", "round" = "round", "puntos_acumulados" = "puntos_acumulados")) %>% 
  full_join(., alo_vs_vandoorne, c("driverRef"= "driverRef", "resultId" = "resultId", "raceId" = "raceId", "constructorId" = "constructorId", "position" = "position", "points" = "points", "name.x" = "name.x", "year" = "year", "round" = "round", "puntos_acumulados" = "puntos_acumulados")) %>% 
  full_join(., alo_vs_ocon, c("driverRef"= "driverRef", "resultId" = "resultId", "raceId" = "raceId", "constructorId" = "constructorId", "position" = "position", "points" = "points", "name.x" = "name.x", "year" = "year", "round" = "round", "puntos_acumulados" = "puntos_acumulados"))


#------------------------------
#el nano contra hamilton
fotos_ALO_vs_HAM <- c("./imagenes/pilotos/alonso.png", "./imagenes/pilotos/hamilton.png")
fotos_esp_ing <- c("./imagenes/paises/espanya.png", "./imagenes/paises/uk.png")
n_carreras_alo_ham <- n_carreras_nom %>% filter(driverRef %in% c("alonso", "hamilton"))

n_victorias_alo_ham <- victorias_con_nombre %>% filter(driverRef %in% c("alonso", "hamilton"))

alo_vs_ham <- full_join(n_carreras_alo_ham, n_victorias_alo_ham, c("driverRef"= "driverRef")) %>% select( driverRef, numero_carreras, n_victorias) %>% add_column(fotos_esp_ing, fotos_ALO_vs_HAM) 

3. The plan

3.1 Un paseo por la historia

El nacimiento de la Fórmula 1 se remonta a 1950, donde la FIA, Federación Internacional del Automóvil, decidió unir varios grandes premios de diferentes países, para crear el ampeonato undial de pilotos. El primer gran premio se celebró en el circuito de Silverstone, el 13 de mayo de 1950. Desde entonces, La Fórmula 1 ha ido evolucionando, tanto a nivel de coches, circuitos, o logos, para acabar siendo el espectáculo que es en la actualidad.

Coches

El automóvil puede ser el elemento que mayores cambios ha experimetnado con el paso del tiempo. En los años 50, las escuderias más destacables eran los propios fabricantes de vehículos, por ejemplo Maserati o Alfa Romeo. Los coches en esta década se caracterizaban por tener un motor frontal, a diferencia de lo que pasaría en años posteriores.

A partir de la década de los 60, se comenzaron a utilizar vehículos con motor central, suponiendo una importante mejora en el desempeño de los coches. Además, se dio peso a otros aspectos, como la composición del chasis, siendo la escudería lotus pionera en introducir los chasis monocasco de aluminio.

En los 70, la aerodinámica pasó a tener un papel fundamental, introduciendose el efecto suelo, q permitía rodar a mayor velocidad en las curvas. Entre 1980 y 1990 destacan las ayudas electrónicas, como por ejemplo la suspensión activa, el cambio de marchas semi-automático, o el control de tracción.

Desde entonces, hasta la actualidad, los cammbios en los coches no han sido tan relevantes, produciendose un equilibrio en las mejoras de las distintas partes del vehículo: aerodinámica, chasis y motor.

coche1950 <- image_read("./imagenes/coches/1950.jpg") %>% image_scale(., "500") %>%  image_annotate(., "1950", size = 40, gravity = "southwest", color = "white")
coche1960 <- image_read("./imagenes/coches/1960.jpg") %>% image_scale(., "500")%>%  image_annotate(., "1960", size = 40, gravity = "southwest", color = "white")
coche1970 <- image_read("./imagenes/coches/1970.jpg") %>% image_scale(., "500")%>%  image_annotate(., "1970", size = 40, gravity = "southwest", color = "white")
coche1980 <- image_read("./imagenes/coches/1980.jpg") %>% image_scale(., "500")%>%  image_annotate(., "1980", size = 40, gravity = "southwest", color = "white")
coche1990 <- image_read("./imagenes/coches/1990.jpg") %>% image_scale(., "500")%>%  image_annotate(., "1990", size = 40, gravity = "southwest", color = "white")
coche2005 <- image_read("./imagenes/coches/2005.jpg") %>% image_scale(., "500")%>%  image_annotate(., "2005", size = 40, gravity = "southwest", color = "white")
coche2020 <- image_read("./imagenes/coches/2020.jpg") %>% image_scale(., "500")%>%  image_annotate(., "2020", size = 40, gravity = "southwest", color = "white")
coches <- c(coche1950, coche1960, coche1970, coche1980, coche1990, coche2005, coche2020)

image_animate(image_scale(coches), fps = 0.5)

Logos

Logo de 1985 a 1986

Aunque no tan espectacular, también se ha producido ua evolución de la estética del logo, pasando de una imagen más cargada, en la que aparece hasta el símbolo de la FIA, al logo actual, compuesto por la F y el 1.

Logo de 1950 a 1986

Logo de 1987 a 1993

Logo de 1987 a 1993

Logo de 1994 a 2017

Logo de 1994 a 2017

Logo Actual

LOGO desde 2018 hasta la actualidad

Capítulo oscuro del deporte

Hay que ser conscientes que, de igual manera que la Formula 1 es espectacular, sus pilotos se exponen a un gran riesgo, debido a las velocidades que alcanzan. Prueba de ello es, el gráfico mostrado a continuación, en el cual se refleja todas las muertes de pilotos producidas en la F1. El total es de 42, siendo la peor decada los años 50, produciendose 15 fallecimientos.

Sin embargo, la tendencia ha sido claramente negativa, debido a las diferentes medidas de seguridad que se han ido incorporando. La última introducción ha sido el halo, centrado en evitar golpes o aplastamientos de la cabeza del piloto. Otras mejoras destacadas han sido, las proteciones y grava en los circuitos, los monos ignífugos o la reglamentación en el diseño del casco.

gg_muertes <- ggplot(muertesf1_final, aes(x = fecha_muerte, y = muertesxanyo )) +  geom_bar(stat = "identity", fill = "white", colour = "white") + geom_smooth(colour = "cyan", se = FALSE) + labs(x = "Año" , y = "Número de muertes")  + theme(axis.line = element_line(colour = "white"),
    axis.ticks = element_line(colour = "white"),
    panel.grid.major = element_line(colour = "gray13"),
    panel.grid.minor = element_line(colour = "gray13"),
    axis.title = element_text(colour = "white"),
    axis.text = element_text(colour = "white"),
    plot.title = element_text(colour = "white"),
    panel.background = element_rect(fill = "gray13",
        colour = "white"), plot.background = element_rect(fill = "gray13")) +labs(colour = "white") + theme(panel.grid.major = element_line(colour = "gray38",
    linetype = "dotted"), panel.grid.minor = element_line(colour = NA),
    plot.title = element_text(size = 25,
        hjust = 0.5)) +labs(title = "Accidentes mortales por año") + geom_text(data = data.frame(x = 2004.10522642875, y = 0.237450516942241, 
    label = "Tendencia negativa"), mapping = aes(x = x, y = y, 
    label = label), colour = "cyan", inherit.aes = FALSE, size = 3)

ggplotly(gg_muertes)

3.2 Lo más destacado

Audencias

audiencias <- rio::import(file = "./datos/audienciasF1.csv")


gg_audiencias <- ggplot(audiencias, aes(x=year, y= numero_espectadores)) +
  geom_area() +
  geom_point( size=1.5, color="cyan", fill=alpha("cyan", 8), shape=21, stroke=2) +  
  geom_line(color="#69b3a2", size=1) +
  scale_x_continuous(
    breaks = seq(2004, 2020, 1),
    limits = c(2003, 2021)) + labs(x = "Año", y = "Numero de espectadores" )  + theme(panel.background = element_rect(fill = "gray13"),
    plot.background = element_rect(fill = "gray13")) + theme(axis.line = element_line(colour = "white"),
    panel.grid.major = element_line(colour = "gray20"),
    panel.grid.minor = element_line(colour = "gray20"),
    axis.text = element_text(colour = "white"),
    legend.position = "none") + theme(axis.title = element_text(colour = "white"),
    plot.title = element_text(colour = "white",
        hjust = 0.5)) +labs(title = "Evolución de la audiencia",
    colour = "white") + theme(axis.text.x = element_text(size = 4))


ggplotly(gg_audiencias)

Presupuestos

presupuestos <- read_excel("datos/presupuestos.xlsx")

gg_presup <- ggplot(presupuestos, aes(year, Presupuesto, color = Escuderia)) + 
  geom_point() + geom_line() + 
  labs(x = "Año", y = "Presupuesto en €" ) +
    scale_x_continuous(
    breaks = seq(2015, 2023, 1),
    limits = c(2014, 2024)) + 
  scale_y_continuous( breaks = seq(0, 700000000, 100000000),
    limits = c(0, 600000000))  + theme(axis.ticks = element_line(colour = "white"),
    panel.grid.major = element_line(colour = "white",
        linetype = "blank"), panel.grid.minor = element_line(colour = "white",
        linetype = "blank"), axis.title = element_text(size = 14,
        face = "bold", colour = "cyan", vjust = 0.75),
    axis.text = element_text(colour = "white"),
    plot.title = element_text(size = 16,
        face = "bold", colour = "cyan", hjust = 0.5,
        vjust = 0.75), legend.text = element_text(face = "bold",
        colour = "cyan"), legend.title = element_text(size = 13,
        face = "bold", colour = "cyan"),
    panel.background = element_rect(fill = "gray13",
        colour = "white"), plot.background = element_rect(fill = "gray13"),
    legend.key = element_rect(fill = "gray13"),
    legend.background = element_rect(fill = "gray13")) +labs(title = "PRESUPUESTO DE CADA EQUIPO POR TEMPORADA") + theme(panel.grid.major = element_line(colour = NA),
    panel.grid.minor = element_line(colour = NA),
    axis.title = element_text(size = 11),
    plot.title = element_text(size = 14),
    legend.text = element_text(size = 9),
    legend.title = element_text(size = 11),
    panel.background = element_rect(fill = "gray13",
        colour = NA), plot.background = element_rect(fill = "gray13",
        colour = NA)) + theme(legend.key = element_rect(fill = "gray13"),
    legend.background = element_rect(fill = "gray13")) + theme(axis.line = element_line(colour = "gray20",
    linetype = "solid"), panel.grid.major = element_line(colour = "gray15",
    linetype = "solid"))
 
ggplotly(gg_presup) #para que sea interactivo

Nacionalidades

Mapa

ggplotly(gg_pilotos_por_paises)

Tabla

set_flextable_defaults(
  font.size = 15,
  font.color = "white",
  table.layout = "fixed", 
  background.color = "gray13")

flex_piloto <- flextable(nacionalidad)

small_border = fp_border(color="gray50", width = 2)

flex_piloto1 <- border_outer(flex_piloto, part="all", border = small_border )


theme_vader(flex_piloto1)

Pilotos con más victorias

ggplot(victorias2, aes(x = reorder(driverRef,suma_vic), suma_vic)) + 
  geom_line(size=5, colour = "cyan") +
  coord_flip() +
  theme(plot.subtitle = element_text(hjust = 0.5),
    plot.caption = element_text(size = 15,
        colour = "white", hjust = 0), axis.line = element_line(colour = "gray20",
        linetype = "solid"), panel.grid.major = element_line(linetype = "blank"),
    panel.grid.minor = element_line(linetype = "blank"),
    axis.title = element_text(colour = "cyan"),
    axis.text = element_text(colour = "cyan"),
    axis.text.x = element_text(colour = "white"),
    axis.text.y = element_text(colour = "white"),
    plot.title = element_text(size = 17,
        colour = "white", hjust = 0.5), panel.background = element_rect(fill = "gray13",
        colour = "gray13", linetype = "solid"),
    plot.background = element_rect(fill = "gray13",
        colour = "gray13", linetype = "solid")) +labs(title = 'Pilotos con más victorias' ,x = "Pilotos",
    y = "Nº victorias") + theme(plot.subtitle = element_text(colour = "gray50"),
    plot.title = element_text(face = "bold",
        colour = "cyan")) +labs(title = "PILOTOS CON MÁS VICTORIAS",
    subtitle = ) #+ transition_reveal(date)

Remando a contracorriente

trulli <- readPNG("./imagenes/pilotos/trulli.png")
kovalainen <- readPNG("./imagenes/pilotos/kovalainen.png")
vettel <- readPNG("./imagenes/pilotos/vettel.png")
raikkonen <- readPNG("./imagenes/pilotos/raikkonen.png")
schumacher <- readPNG("./imagenes/pilotos/schumacher.png")
hamilton <- readPNG("./imagenes/pilotos/hamilton.png")
montoya <- readPNG("./imagenes/pilotos/montoya.png")
alonso <- readPNG("./imagenes/pilotos/alonso.png")

trulli_grob <- rasterGrob(trulli, interpolate=TRUE)
kovalainen_grob <- rasterGrob(kovalainen, interpolate=TRUE)
vettel_grob <- rasterGrob(vettel, interpolate=TRUE)
raikkonen_grob <- rasterGrob(raikkonen, interpolate=TRUE)
schumacher_grob <- rasterGrob(schumacher, interpolate=TRUE)
hamilton_grob <- rasterGrob(hamilton, interpolate=TRUE)
montoya_grob <- rasterGrob(montoya, interpolate=TRUE)
alonso_grob <- rasterGrob(alonso, interpolate=TRUE)


ggremontados <- ggplot(puestos_remont_piloto_recient, aes(x = reorder(driverRef, remontados), remontados))  + geom_bar(stat = "identity") + coord_flip() + labs(x = "Pilotos", y = "Nº de puestos remontados" ) + annotation_custom(alonso_grob, xmin= -15, xmax=17, ymin= 18, ymax=20) +
  annotation_custom(kovalainen_grob, xmin= -20, xmax=24, ymin= 18.65, ymax=20) +
  annotation_custom(montoya_grob, xmin= -26.7, xmax=33, ymin= 18, ymax=21.2) +
  annotation_custom(trulli_grob, xmin= -32, xmax=40., ymin= 18.3, ymax=19.55) +
  annotation_custom(hamilton_grob, xmin= -32, xmax=42.2, ymin= 19, ymax=21.8) +
  annotation_custom(schumacher_grob, xmin= -32, xmax=44.1, ymin= 19.2, ymax=20.5) +
  annotation_custom(raikkonen_grob, xmin= -32, xmax=46.1, ymin= 19, ymax=21) +
  annotation_custom(vettel_grob, xmin= -32, xmax=48.1, ymin= 19, ymax=21.2) +
    theme(axis.line = element_line(colour = "white"),
    axis.ticks = element_line(colour = NA),
    panel.grid.major = element_line(colour = "cyan",
        linetype = "blank"), panel.grid.minor = element_line(colour = "gray20"),
    axis.title = element_text(face = "bold",
        colour = "gray50"), axis.text = element_text(size = 11,
        colour = "cyan"), axis.text.x = element_text(colour = "cyan"),
    axis.text.y = element_text(colour = "cyan"),
    plot.title = element_text(size = 15,
        face = "bold", colour = "cyan", hjust = 0.45,
        vjust = 0.75), panel.background = element_rect(fill = "gray13",
        linetype = "solid"), plot.background = element_rect(fill = "gray13",
        colour = "cyan", linetype = "solid")) +labs(title = "MAYORES REMONTADAS EN LA HISTORIA")
  

ggremontados

Mundiales por escuderias y pilotos

En valores relativos

#datos de escuderias pa quien quiera hacer algo
#escuderias <- rio::import(file = "./datos/constructors.csv")
#escuderias2 <- rio::import(file = "./datos/constructor_standings.csv")
#result_escuderias <- rio::import(file = "./datos/constructor_results.csv")

#pilotos <- rio::import(file = "./datos/drivers.csv")
#resultados <- rio::import(file = "./datos/results.csv")
#carreras <- rio::import(file = "./datos/races.csv")
#escuderiasesp <- escuderias %>% filter(nationality == "Spanish") #escuderias españolas

#campeones_esc <- full_join(pilotos, resultados, c("driverId" = "driverId")) %>% full_join(., carreras, c("raceId" = "raceId")) %>% select(driverId, driverRef, nationality, constructorId, points, year, round) %>% full_join(., escuderias, c("constructorId" = "constructorId")) %>% select(driverId, driverRef, nationality.x, constructorId, points, year, name, round) %>%  group_by(year, driverRef) %>%  mutate(puntos_totales = cumsum(points)) %>% ungroup() %>% group_by(year) %>% slice_max(puntos_totales, n=1) %>% select(name, driverRef) %>% group_by(name, driverRef) %>% mutate(total_camp = sum( NN = n())) %>% arrange(name) 




#library(treemap)
#library(d3treeR)


# basic treemap
#gg_esc_campeones <- treemap(campeones_esc,
            #index=c("name","driverRef"),
            #vSize="total_camp",
            #type="index",
            #vColor = "name",
            #fontsize.labels=c(25,17),
            #bg.labels=c("transparent"),
            #palette = "Set2",
            #align.labels=list(
              #c("center", "center"), 
              #c("center", "bottom")),
            #title = "Escuderías con más campeones",
            #title.legend = "Escuderías")   
inter_camp <- d3tree2(gg_esc_campeones ,  rootname = "Escuderías y Campeones")
inter_camp

En valores absolutos

campeones_esc <- full_join(pilotos, resultados, c("driverId" = "driverId")) %>% full_join(., carreras, c("raceId" = "raceId")) %>% select(driverId, driverRef, nationality, constructorId, points, year, round) %>% full_join(., escuderias, c("constructorId" = "constructorId")) %>% select(driverId, driverRef, nationality.x, constructorId, points, year, name, round) %>%  group_by(year, driverRef) %>%  mutate(puntos_totales = cumsum(points)) %>% ungroup() %>% group_by(year) %>% slice_max(puntos_totales, n=1) %>% ungroup() %>% count(name) %>% arrange(desc(n))

campeones_esc$n=as.factor(campeones_esc$n)

gg_campeones_es <- ggplot(campeones_esc, aes(x=name, y=n)) +
  geom_bar(stat="identity", width=2, color="white") + 
  theme(axis.line = element_line(colour = "gray13"),
    axis.ticks = element_line(colour = "gray13"),
    panel.grid.major = element_line(colour = "gray13"),
    panel.grid.minor = element_line(colour = "gray13"),
    axis.title = element_text(family = "Bookman",
        size = 8, face = "bold"), axis.text = element_text(face = "bold",
        colour = "cyan"), axis.text.x = element_text(colour = "gray13"),
    axis.text.y = element_text(colour = "gray13"),
    plot.title = element_text(family = "Bookman",
        size = 14, face = "bold", colour = "cyan", hjust=0.5),
    legend.text = element_text(size = 9,
        face = "bold", colour = "cyan"),
    legend.title = element_text(size = 8,
        face = "bold", colour = "gray13"),
    panel.background = element_rect(fill = "gray13",
        colour = "gray13", linetype = "solid"),
    plot.background = element_rect(fill = "gray13",
        colour = "gray13", linetype = "solid"),
    legend.key = element_rect(fill = "cyan"),
    legend.background = element_rect(fill = "gray13")) +labs(title = "CAMPEONATOS POR ESCUDERIA",
    x = NULL, y = NULL)


ggplotly(gg_campeones_es)

Mundiales por pilotos y nacionalidad

id <- rownames(campeones)
campeones <- cbind(id=id, campeones)
campeones[, c(1)] <- sapply(campeones[, c(1)], as.numeric)

label_campeones <- campeones
number_of_bar <- nrow(label_campeones)

angle <- 90 - 360 * (label_campeones$id-0.5) /number_of_bar    
label_campeones$hjust <- ifelse( angle < -90, 1, 0)
label_campeones$angle <- ifelse(angle < -90, angle+180, angle)

base_campeones <- campeones %>% 
  group_by(nationality.x) %>% 
  summarise(start=min(id), end=max(id)) %>% 
  rowwise() %>% 
  mutate(title=mean(c(start, end)))

grid_campeones <- base_campeones
grid_campeones$end <- grid_campeones$end[ c( nrow(grid_campeones), 1:nrow(grid_campeones)-1)] + 1
grid_campeones$start <- grid_campeones$start - 1
grid_campeones <- grid_campeones[-1,]

gg_circ_victorias <- ggplot(campeones, aes(x=as.factor(year), y=total_campeonatos, fill=nationality.x, color = nationality.x)) + geom_bar(aes(x=as.factor(id), y=total_campeonatos, fill=nationality.x), stat="identity", alpha=0.5) +
  
  geom_segment(data=grid_campeones, aes(x = 0, y = 8, xend = 32, yend = 8), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 0, y = 6, xend = 32, yend = 6), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 0, y = 4, xend = 32, yend = 4), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 0, y = 2, xend = 32, yend = 2), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  
  annotate("text", x = rep(max(campeones$id),4), y = c(2, 4, 6, 8), label = c("2", "4", "6", "8") , color="white", size=3 , angle=0, fontface="bold", hjust=1) +
  
   geom_bar(aes(x=as.factor(id), y=total_campeonatos, fill=nationality.x), stat="identity", alpha=0.5) +
  ylim(-10,21) +
  theme_minimal() +
  theme(
    legend.position = "none",
    axis.text = element_blank(),
    axis.title = element_blank(),
    panel.grid = element_blank(),
    plot.margin = unit(rep(-1,4), "cm") ) +
  coord_polar() + 
  geom_text(data=label_campeones, aes(x=id, y=10, label=driverRef, hjust=hjust), color="white", fontface="bold",alpha=0.6, size=3.5, angle= label_campeones$angle, inherit.aes = FALSE ) +

  geom_segment(data=grid_campeones, aes(x = 0.70, y = -1, xend = 2.45, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE )  +
  geom_segment(data=grid_campeones, aes(x = 2.6, y = -1, xend = 3.55, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 3.65, y = -1, xend = 5.45, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 5.55, y = -1, xend = 7.35, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 7.5, y = -1, xend = 10.50, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 10.7, y = -1, xend = 19.20, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 19.4, y = -1, xend = 20.3, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 20.45, y = -1, xend = 23.4, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) + 
  geom_segment(data=grid_campeones, aes(x = 23.65, y = -1, xend = 24.35, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) + 
  geom_segment(data=grid_campeones, aes(x = 24.60, y = -1, xend = 27, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 27.2, y = -1, xend = 29.5, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 29.7, y = -1, xend = 30.5, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) + 
  geom_segment(data=grid_campeones, aes(x = 30.7, y = -1, xend = 31.5, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 31.7, y = -1, xend = 32.5, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_campeones, aes(x = 32.7, y = -1, xend = 33.5, yend = -1), colour = "white", alpha=1, size=0.3 , inherit.aes = FALSE ) + theme(legend.text = element_text(colour = "white"),
    legend.title = element_text( colour = "white"), 
     legend.background = element_rect(fill = "gray13", colour = "gray13"),
    legend.key = element_rect(fill = "gray13"),
    legend.position = "right",
    panel.background = element_rect(fill = "gray13" , colour = "gray13"),
    plot.background = element_rect(fill = "gray13" , colour = "gray13"))+labs(colour = "Nacionalidad", fill = "Nacionalidad")
#gg_circ_victorias
#las siguientes lineas de codigo se utilizan para eliminar los bordes blancos
ggsave("./plots/gg_circ_victorias.png", width = 8, height = 5)

Campeones del mundo

3.3 Temporada 2021

Campeón del mundo

Verstappen

Verstappen - Nuevo Campeón 2021

Final de infarto

salida <- image_read("./imagenes/CAMPEON/hamilton_adel.jpg") %>% image_scale(., "500")%>%  image_annotate(., "Hamilton se pone por delante", size = 20, gravity = "northwest", color = "cyan", boxcolor = "gray13")
latifi <- image_read("./imagenes/CAMPEON/latifi.jpg") %>% image_scale(., "500")%>%  image_annotate(., "Accidente de Latifi", size = 40, gravity = "northwest", color = "cyan", boxcolor = "gray13")
safety <- image_read("./imagenes/CAMPEON/safety.jpg") %>% image_scale(., "500")%>%  image_annotate(., "Sale el safety car", size = 40, gravity = "northwest", color = "cyan", boxcolor = "gray13")
rueda_a_rueda <- image_read("./imagenes/CAMPEON/ruedaarueda.jpeg") %>% image_scale(., "500")%>%  image_annotate(., "Igualdad máxima", size = 30, gravity = "northwest", color = "cyan", boxcolor = "gray13")
meta <- image_read("./imagenes/CAMPEON/verstappen_gana.jpg") %>% image_scale(., "500")%>%  image_annotate(., "Verstappen se hace con la victoria", size = 20, gravity = "northwest", color = "cyan", boxcolor = "gray13")
trofeo <- image_read("./imagenes/CAMPEON/campeon_trofeo.jpg") %>% image_scale(., "500")%>%  image_annotate(., "Nuevo campeón del mundo", size = 30, gravity = "northwest", color = "cyan", boxcolor = "gray13")
last_race <- c(salida, latifi, safety, rueda_a_rueda, meta, trofeo)

image_animate(image_scale(last_race), fps = 0.5)

Verstappen vs Hamilton

vers_vs_ham <- data.frame(
  "nombre" = c("Max Verstappen", "Lewis Hamilton"),
  "piloto" = c("./imagenes/pilotos/verstappen.jpg","./imagenes/pilotos/hamilton.png"),
  "pais" = c("./imagenes/paises/holanda.png", "./imagenes/paises/uk.png"),
  "escuderia" = c("./imagenes/escuderias/redbull.png", "./imagenes/escuderias/mercedes.png"),
  "puntos" = c(395.5, 387.5),
  "victorias" = c(10, 8),
  "podiums" = c(18, 17),
  "poles" = c(10, 5),
  "vueltas_rapidas" = c(6, 6))
  

 
tabla_ver_ham <- vers_vs_ham %>% gt() %>% 
  text_transform( locations = cells_body(columns = c(piloto)), fn = function(x) {gt::local_image(x, height = 80)}) %>% 
  text_transform( locations = cells_body(columns = c(pais)), fn = function(x) {gt::local_image(x, height = 60)}) %>%  
  text_transform( locations = cells_body(columns = c(escuderia)), fn = function(x) {gt::local_image(x, height = 80)}) %>% 
  tab_header(title = md("**Verstappen vs Hamilton**"), subtitle = md("2021")) %>%   cols_label(
    nombre = html(""),
    piloto = html(""),
    pais = html(""),
    escuderia = html("Escudería"),
    puntos = html("Puntos"),
    victorias = html("Victorias"),
    podiums = html("Podiums"),
    poles = html("Poles"),
    vueltas_rapidas = html("Vueltas rápidas")) %>%  
  tab_options(table.background.color = "gray13",   table.font.color.light = "cyan") %>% 
  cols_align(align = "center",
  columns = everything())


tabla_ver_ham
Verstappen vs Hamilton
2021
Escudería Puntos Victorias Podiums Poles Vueltas rápidas
Max Verstappen 395.5 10 18 10 6
Lewis Hamilton 387.5 8 17 5 6

Parrilla de pilotos

pilotos_2021 <- full_join(carreras, resultados, c("raceId" = "raceId") ) %>% 
  full_join(.,pilotos, c("driverId"="driverId")) %>% 
  filter(year=="2021") %>% 
  select(forename,surname, year) %>% distinct(forename,surname) %>% na.omit() %>% arrange(surname) %>% str_replace_all(., "é", "é") %>% str_replace_all(., "ä", "ä") %>% str_replace_all(., "ö", "ö")

nombres_normales <- c("Alonso", "Bottas", "Gasly", "Giovinazzi", "Hamilton", "Latifi", "Leclerc", "Mazepin", "Norris", "Ocon", "Pérez", "Räikkönen", "Ricciardo", "Russell", "Sainz", "Schumacher", "Stroll", "Tsunoda", "Verstappen", "Vettel")

pilotos_2021 <-  full_join(carreras, resultados, c("raceId" = "raceId") ) %>% 
  full_join(.,pilotos, c("driverId"="driverId")) %>% 
  filter(year=="2021") %>% 
  select(forename,surname, year) %>% distinct(forename,surname) %>% na.omit() %>% arrange(surname) %>% add_column(nombres_normales)  
 

# Pérez
# Räikkönen
fotos_pil_2021 <- c("./imagenes/pilotos/alonso.png", "./imagenes/pilotos/bottas.png", "./imagenes/pilotos/gasly.png", "./imagenes/pilotos/giovinazzi.jpg", "./imagenes/pilotos/hamilton.png", "./imagenes/pilotos/latifi.png", "./imagenes/pilotos/leclerc.png", "./imagenes/pilotos/mazepin.png", "./imagenes/pilotos/norris.png", "./imagenes/pilotos/ocon.jpg", "./imagenes/pilotos/perez.png", "./imagenes/pilotos/raikkonen.png", "./imagenes/pilotos/ricciardo.png", "./imagenes/pilotos/russell.png", "./imagenes/pilotos/sainz.png", "./imagenes/pilotos/mick.png", "./imagenes/pilotos/stroll.png", "./imagenes/pilotos/tsunoda.png", "./imagenes/pilotos/verstappen.jpg", "./imagenes/pilotos/vettel.png")

fotos_pais_2021 <- c("./imagenes/paises/espanya.png", "./imagenes/paises/finlandia.png", "./imagenes/paises/francia.png", "./imagenes/paises/italia.png","./imagenes/paises/uk.png", "./imagenes/paises/canada.png","./imagenes/paises/monaco.png", "./imagenes/paises/rusia.png","./imagenes/paises/uk.png", "./imagenes/paises/francia.png","./imagenes/paises/mexico.png", "./imagenes/paises/finlandia.png","./imagenes/paises/australia.png", "./imagenes/paises/uk.png","./imagenes/paises/espanya.png", "./imagenes/paises/alemania.png","./imagenes/paises/canada.png", "./imagenes/paises/japon.png","./imagenes/paises/holanda.png", "./imagenes/paises/alemania.png")

fotos_esc_2021 <- c("./imagenes/escuderias/alpine.png","./imagenes/escuderias/mercedes.png","./imagenes/escuderias/alphatauri.png", "./imagenes/escuderias/alfaromeo.jpg","./imagenes/escuderias/mercedes.png", "./imagenes/escuderias/williams.png","./imagenes/escuderias/ferrari.png", "./imagenes/escuderias/haas.png","./imagenes/escuderias/mclaren.png", "./imagenes/escuderias/alpine.png","./imagenes/escuderias/redbull.png", "./imagenes/escuderias/alfaromeo.jpg","./imagenes/escuderias/mclaren.png", "./imagenes/escuderias/williams.png","./imagenes/escuderias/ferrari.png", "./imagenes/escuderias/haas.png","./imagenes/escuderias/aston.png", "./imagenes/escuderias/alphatauri.png","./imagenes/escuderias/redbull.png", "./imagenes/escuderias/aston.png")

pilotos_2021 <- pilotos_2021 %>%
  add_column(fotos_pil_2021, fotos_pais_2021, fotos_esc_2021) %>% select(nombres_normales, fotos_pil_2021, fotos_pais_2021, fotos_esc_2021)


mundial_2021 <- pilotos_2021 %>% gt() %>% text_transform( locations = cells_body(columns = c(fotos_pil_2021)), fn = function(x) {gt::local_image(x, height = 100)}) %>% text_transform( locations = cells_body(columns = c(fotos_pais_2021)), fn = function(x) {gt::local_image(x, height = 50)}) %>% text_transform( locations = cells_body(columns = c(fotos_esc_2021)), fn = function(x) {gt::local_image(x, height = 70)}) %>% tab_header(title = md("**Pilotos 2021**"), subtitle = md("Parrilla")) %>%   cols_label(
    nombres_normales = html(""),
    fotos_pil_2021 = html(""),
    fotos_pais_2021 = html(""),
    fotos_esc_2021 = html("")) %>%  
  tab_options(table.background.color = "gray13",   table.font.color.light = "cyan") %>% 
  cols_align(align = "center",
  columns = everything())


#mundial_2021

Templos

globo_circ <-create_globe() %>% globe_pov(45.61560, 9.281110) %>% globe_bars(coords(lat, lng, label  = variables, color = round2), data = carreras_21_v2)  %>% scale_bars_color()
#globo_circ

3.4 El nano

Alonso vs compañeros de equipo

gc() #instruccion para que cargue el grafico, al ser tan complejo da error de no sé qué pero con esto funciona
#>            used  (Mb) gc trigger  (Mb) max used  (Mb)
#> Ncells  5029026 268.6    8721117 465.8  8721117 465.8
#> Vcells 16461297 125.6   27946008 213.3 27944246 213.2
ggalo_vs_all <- ggplot(data = ALO_VS_ALL, aes(round, puntos_acumulados, color = driverRef)) +
  geom_line() +
  geom_point() + 
  labs(title = "Alonso contra el mundo",
       subtitle = "Alonso VS cada compañero de equipo",
       y = "Puntos", x = "") + theme(axis.line = element_line(colour = "gray30",
    linetype = "solid"), axis.ticks = element_line(colour = "gray30"),
    panel.grid.major = element_line(colour = "gray20"),
    panel.grid.minor = element_line(linetype = "blank"),
    axis.title = element_text(size = 15,
        colour = "white"), axis.text = element_text(colour = "white"),
    plot.title = element_text(size = 20,
        colour = "white", hjust = 0.5), legend.text = element_text(colour = "white"),
    legend.title = element_text(colour = "white"),
    panel.background = element_rect(fill = "gray13",
        colour = "gray13", linetype = "solid"),
    plot.background = element_rect(fill = "gray13",
        colour = "gray13", linetype = "solid"),
    legend.key = element_rect(fill = "gray13",
        colour = "gray13"), legend.background = element_rect(fill = "gray13",
        colour = "gray13")) +labs(x = "Nº carrera", colour = "Piloto") + theme(plot.subtitle = element_text(size = 10,
    hjust = 0.5)) + facet_wrap( ~ year) + transition_reveal(round)

#ggalo_vs_all

Alonso vs Hamilton

#se necesita tener cargado "n_carreras_nom", "victorias_con_nombre"
#1234

alo_vs_ham_tabla <- alo_vs_ham %>% gt() %>% text_transform( locations = cells_body(columns = c(fotos_esp_ing)), fn = function(x) {gt::local_image(x, height = 50)}) %>% text_transform( locations = cells_body(columns = c(fotos_ALO_vs_HAM)), fn = function(x) {gt::local_image(x, height = 100)}) %>% tab_header(title = md("**Alonso vs Hamilton**"), subtitle = md("Comparación")) %>%   cols_label(
    driverRef = html(""),
    numero_carreras = html("Nº carreras"),
    n_victorias = html("Nº victorias"),
    fotos_esp_ing = html("País"),
    fotos_ALO_vs_HAM = html("")) %>%  
  tab_options(table.background.color = "gray13",   table.font.color.light = "cyan") %>% 
  cols_align(align = "center",
  columns = everything())

alo_vs_ham_tabla
Alonso vs Hamilton
Comparación
Nº carreras Nº victorias País
alonso 323 32
hamilton 275 98

4. Trabajos en los que te has basado

Con los datos que hemos encontrado, existen una serie de códigos que ya trabajan con estos datos, especialmente este, a partir del cual, sobre todo, nos hemos fijado en la estética de los gráficos y las imagenes con las que los acompañaba. También hemos obtenido ideas para trabajar los datos, pero en menor medida que el apartado visual, ya que el trabajo citado se centra unicamente en la temporada actual, mientras que Alt+ Formula 1 combina tanto la actualidad como la historia en general de la F1.

5. Bibliografía

La gran parte del trabajo se ha centrado en los datos obtenidos a partir de Kaggle, por lo que no son muchas las páginas auxiliares que hemos utilizado.
Para la obtención de las audiencias se han utilizado tanto esta página web , como este post de twitter.

LS0tDQp0aXRsZTogIkFsdCArIEZvcm11bGEgMSINCmF1dGhvcjogIkNheWV0YW5vIFJvbWVybyBNb250ZWFndWRvIChjYXJvbW9uM0BhbHVtbmkudXYuZXMpICBcblxuIEFsZWphbmRybyBHYXJjw61hIFNlZ2FycmEgKGFnYXJzZTRAYWx1bW5pLnV2LmVzKSAgXG4gXG4gQ2FybG9zIEdhcmPDrWEgQ2FzdGlsbGEgKGdhcmNhczhAYWx1bW5pLnV2LmVzKS4gXG5cbiBVbml2ZXJzaXRhdCBkZSBWYWzDqG5jaWEiDQpkYXRlOiAiRGljaWVtYnJlIGRlIDIwMjEgKGFjdHVhbGl6YWRvIGVsIGByIGZvcm1hdChTeXMudGltZSgpLCAnJWQtJW0tJVknKWApIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgICNjc3M6ICIuL2Fzc2V0cy9teV9jc3NfZmlsZS5jc3MiDQogICAgdGhlbWU6IGRhcmtseQ0KICAgIGhpZ2hsaWdodDogdGFuZ28gDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAzIA0KICAgIHRvY19mbG9hdDogDQogICAgICBjb2xsYXBzZWQ6IHRydWUNCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUNCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UNCiAgICBkZl9wcmludDoga2FibGUNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQplZGl0b3Jfb3B0aW9uczogDQogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlDQotLS0NCjwhLS0tIGNodW5rIHBhcmEgcXVlIGxhIGZ1ZW50ZSBzZWEgbGEgb2ZpY2lhbCBkZSBsYSBGb3JtdWxhIDEgLS0+DQpgYGB7Y3NzLCBlY2hvPUZBTFNFfSANCkBmb250LWZhY2Ugew0KICBmb250LWZhbWlseTogRjE7DQogIHNyYzogdXJsKGh0dHBzOi8vd3d3LmZvcm11bGExLmNvbS9ldGMvZGVzaWducy9mb20td2Vic2l0ZS9mb250cy9GMVJlZ3VsYXIvRm9ybXVsYTEtUmVndWxhci50dGYpOw0KfQ0KDQpzcGFuew0KICBmb250LWZhbWlseTogRjE7DQp9DQoNCmF7DQogIGZvbnQtZmFtaWx5OiBGMTsNCn0NCg0KLm5hdi1waWxscz5saS5hY3RpdmU+YTpmb2N1cyB7DQogICAgY29sb3I6ICNmZmZmZmY7DQogICAgYmFja2dyb3VuZC1jb2xvcjogbGlnaHRncmF5Ow0KfQ0KDQouY29udGFpbmVyLWZsdWlkLCAuY29udGFpbmVyLWZsdWlkIGgxIHsNCiAgICBmb250LWZhbWlseTogRjE7DQogICAgbGluZS1oZWlnaHQ6IDEuNzsNCn0NCg0KLmNvbnRhaW5lci1mbHVpZCBwIHsNCiAgICBmb250LWZhbWlseTogRjE7DQogICAgY29sb3I6Y3lhbjsNCn0NCg0KaDEsaDIsaDMsaDQsaDUsaDYscCwgdGFibGUgew0KICBmb250LWZhbWlseTogRjE7DQogIGNvbG9yOiBjeWFuDQp9DQpgYGANCg0KYGBge3IgY2h1bmstc2V0dXAsIGluY2x1ZGUgPSBGQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgZXZhbCA9IFRSVUUsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCANCiAgICAgICAgICAgICAgICAgICAgICAjcmVzdWx0cyA9ICJob2xkIiwNCiAgICAgICAgICAgICAgICAgICAgICBjYWNoZSA9IEZBTFNFLCBjYWNoZS5wYXRoID0gIi9jYWNoZXMvIiwgY29tbWVudCA9ICIjPiIsDQogICAgICAgICAgICAgICAgICAgICAgI2ZpZy53aWR0aCA9IDcsICNmaWcuaGVpZ2h0PSA3LCAgIA0KICAgICAgICAgICAgICAgICAgICAgICNvdXQud2lkdGggPSA3LCBvdXQuaGVpZ2h0ID0gNywNCiAgICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZSA9IFRSVUUsICBmaWcuc2hvdyA9ICJob2xkIiwNCiAgICAgICAgICAgICAgICAgICAgICBmaWcuYXNwID0gMC42MjgsIG91dC53aWR0aCA9ICI3NSUiLCBmaWcuYWxpZ24gPSAiY2VudGVyIikNCmtuaXRyOjpvcHRzX2NodW5rJHNldChkZXYgPSAicG5nIiwgZGV2LmFyZ3MgPSBsaXN0KHR5cGUgPSAiY2Fpcm8tcG5nIikpDQpgYGANCg0KYGBge3Igb3B0aW9ucy1zZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQ0Kb3B0aW9ucyhzY2lwZW4gPSA5OTkpICMtIHBhcmEgcXVpdGFyIGxhIG5vdGFjacOzbiBjaWVudMOtZmljYQ0Kb3B0aW9ucygieWFtbC5ldmFsLmV4cHIiID0gVFJVRSkgDQpgYGANCg0KDQpgYGB7ciBrbGlwcHksIGVjaG8gPSBGQUxTRX0NCmtsaXBweTo6a2xpcHB5KHBvc2l0aW9uID0gYygidG9wIiwgInJpZ2h0IikpICMtIHJlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCJybGVzdXIva2xpcHB5IikNCmBgYA0KDQoNCg0KPGhyIGNsYXNzPSJsaW5lYS1ibGFjayI+DQoNCjwhLS0gRWwgcMOhcnJhZm8gZGUgYWJham8gaGFzIGRlIGRlamFybG8gY2FzaSBpZ3VhbCwgc29sbyBIQVMgZGUgU1VTVElUVUlSICJwZXJlenA0NCIgcG9yIHR1IHVzdWFyaW8gZGUgR2l0aHViLS0+DQpUcmFiYWpvIGVsYWJvcmFkbyBwYXJhIGxhIGFzaWduYXR1cmEgIlByb2dyYW1hY2nDs24geSBtYW5lam8gZGUgZGF0b3MgZW4gbGEgZXJhIGRlbCBCaWcgRGF0YSIgZGUgbGEgVW5pdmVyc2l0YXQgZGUgVmFsw6huY2lhIGR1cmFudGUgZWwgY3Vyc28gMjAyMS0yMDIyLiBFbCByZXBvIGRlbCB0cmFiYWpvIGVzdMOhIFthcXXDrV0oaHR0cHM6Ly9naXRodWIuY29tL2NheWV0YW5vMTA4L3RyYWJham9fQmlnRGF0YV9lcXVpcG8pe3RhcmdldD0iX2JsYW5rIn0uIA0KDQo8IS0tIEVsIHDDoXJyYWZvIGRlIGFiYWpvIGhhcyBkZSBkZWphcmxvIGV4YWN0YW1lbnRlIGlndWFsLCBOTyBoYXMgZGUgY2FtYmlhciBuYWRhLS0+DQoNCkxhIHDDoWdpbmEgd2ViIGRlIGxhIGFzaWduYXR1cmEgeSBsb3MgdHJhYmFqb3MgZGUgbWlzIGNvbXBhw7Flcm9zIHB1ZWRlbiB2ZXJzZSBbYXF1w61dKGh0dHBzOi8vcGVyZXpwNDQuZ2l0aHViLmlvL2ludHJvLWRzLTIxLTIyLXdlYi8wNy10cmFiYWpvcy5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9Lg0KDQo8aHIgY2xhc3M9ImxpbmVhLXJlZCI+DQoNCg0KDQo8IS0tTGlicmVyaWEgZGUgcGFxdWV0ZXMgLS0+DQpgYGB7ciBwYWNrYWdlcy1zZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQ0KbGlicmFyeShtZW1lKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGtsaXBweSkgICMtIHJlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCJybGVzdXIva2xpcHB5IikNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KHJpbykNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZ2dhbmltYXRlKQ0KbGlicmFyeShnZ1RoZW1lQXNzaXN0KQ0KbGlicmFyeShnbG9iZTRyKSAgI3JlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCJKb2huQ29lbmUvZ2xvYmU0ciIpDQpsaWJyYXJ5KHJlbW90ZXMpIA0KbGlicmFyeShndCkNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KHRyZWVtYXApICNpbnN0YWxsLnBhY2thZ2VzKHRyZWVtYXApDQpsaWJyYXJ5KGQzdHJlZVIpICNyZW1vdGVzOjppbnN0YWxsX2dpdGh1YigiZDN0cmVlUi9kM3RyZWVSIikNCmxpYnJhcnkobWFnaWNrKQ0KbGlicmFyeShzdHJpbmdyKQ0KbGlicmFyeSh0bWFwKQ0KbGlicmFyeShmbGV4dGFibGUpDQpsaWJyYXJ5KG9mZmljZXIpDQpsaWJyYXJ5KHBuZykNCmxpYnJhcnkoZ3JpZCkNCmBgYA0KDQoNCiMgMS4gSW50cm9kdWNjacOzbg0KDQpMYSBGb3JtdWxhIDEgZXMgdW5vIGRlIGxvcyBkZXBvcnRlcy9lc3BlY3RhY3Vsb3MgIG3DoXMgaW1wb3J0YW50ZXMgZGVsIG11bmRvLCBsb2dyYW5kbyBhIGxvIGxhcmdvIGRlIHN1cyBoaXN0b3JpYSBjYXB0YXIgYSBtaWxsb25lcyB5IG1pbGxvbmVzIGRlIGVzcGVjdGFkb3Jlcy4gTnVldHJvIHRyYWJham8gcHJldGVuZGUgcGxhc21hciBsYSBncmFuZGV6YSBkZSBsYSBGw7NybXVsYSAxIGEgdHJhdsOpcyBkZSBkaXN0aW50b3MgZGF0b3MgcXVlIHB1ZWRlbiB2ZXJzZSBhIGNvbnRpbW51YWNpw7NuLCB0YW50byBwcmVzZW50ZXMgY29tbyBwYXNhZG9zLiBBZGVtw6FzLCBwYXJ0ZSBkZWwgdHJhYmFqbyBzZSBoYSBjZW50cmFkbyBlbiBsYSBmaWd1cmEgZGUgRmVybmFuZG8gQWxvbnNvLCBlbCBwaWxvdG8gY29uIG1heW9yIGltcG9ydGFuY2lhIGVuIEVzcGHDsWEsIHkgdW5vIGRlIGxvcyBtw6FzIHJlbGV2YW50ZXMgZW4gbGEgaGlzdG9yaWEgZGUgbGEgRm9ybXVsYSAxLiAgDQpFbiByZWxhY2nDs24gY29uIGxhIGFzaWduYXR1cmEsIGxhIGVsZWNjacOzbiBkZWwgdGVtYSBzZSBkZWJlIGEgbG8gZnVuZGFtZW50YWwgcXVlIHNvbiBsb3MgZGF0b3MgZW4gZXN0ZSBkZXBvcnRlLCB0YW50byBwYXJhIGxhIGVsYWJvcmFjacOzbiBkZSBlc3RyYXRlZ2lhcywgZWwgZGlzZcOxbyBkZSBsb3MgY29jaGVzIG8gaW5jbHVzbyBkZSBsYXMgcGlzdGFzLiBEZWJpZG8gYSB0b2RhcyBlc3RhcyByYXpvbmVzLCBjcmVlbW9zIHF1ZSBsYSBGMSwgYSBwZXNhciBkZSBubyBzZXIgdW4gdGVtYSByZWxhY2lvbmFkbyBjb24gbGEgZWNvbm9tw61hLCBlbmNhamEgcGVyZmVjdGFtZW50ZSBjb24gbGEgYXNpZ25hdHVyYS4NCg0KIDxjZW50ZXI+KipUSEUgUExBTioqDQoNCmBgYHtyLCBldmFsPSBUUlVFLCBlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCg0KbXlfZm90byA8LSAiaHR0cHM6Ly9lMDAtZWxtdW5kby51ZWNkbi5lcy9hc3NldHMvbXVsdGltZWRpYS9pbWFnZW5lcy8yMDE3LzA1LzEyLzE0OTQ1ODk5MzQ2MzA2LmpwZyINCm1lbWUobXlfZm90bywgIlNFIFZJRU5FIFRSQUJBSkFaTyIsICJNVVkgVFJBTlFVSUxPUyIsIHNpemUgPSAyICwgY29sb3IgPSAiYmx1ZSIsIHZqdXN0ID0gMS4wNSkNCg0KYGBgDQoNCg0KDQoNCiMgMi4gRGF0b3MNCg0KSGVtb3MgZW5jb250cmFkbyBlbiBba2FnZ2xlXShodHRwczovL3d3dy5rYWdnbGUuY29tLykgYmFzdGFudGVzIGNvbmp1bnRvcyBkZSBkYXRvcyBjb24gbG9zIHF1ZSBwb2RlciB0cmFiYWphciwgcGVybyBlc3BlY2lhbG1lbnRlIFtlc3RlXShodHRwczovL3d3dy5rYWdnbGUuY29tL3JvaGFucmFvL2Zvcm11bGEtMS13b3JsZC1jaGFtcGlvbnNoaXAtMTk1MC0yMDIwKSwgcXVlIHBvc2VlIGdyYW4gdmFyaWVkYWQgZGUgZGF0b3MgZW4gbG8gcmVmZXJlbnRlIGEgcGlsb3RvcywgcmVzdWx0YWRvcywgY2lyY3VpdG9zLCB0aWVtcG9zLCBldGMuDQoNCg0KIyMgMi4xLiBQcm9jZXNhbmRvIGxvcyBkYXRvcw0KDQpBIGNvbnRpbnVhY2nDs24gc2UgbXVlc3RyYSB0b2RhIGxhIG1hbmlwdWxhY2nDs24gZGUgbG9zIGRhdG9zLCBhIHBhcnRpciBkZWwgY29uanVudG8gZGUgZGF0b3MgbW9zdHJhZG8gYW50ZXJpb3JtZW50ZSwgeSBxdWUgcG9zdGVyaW9ybWVudGUgc29uIHV0aWxpemFkb3MgcGFyYSBsYSByZWFsaXphY2nDs24gZGUgbG9zIGRpc3RpbnRhcyBwYXJ0ZXMgcXVlIGZvcm1hbiBlbCB0cmFiYWpvLg0KDQpgYGB7ciwgZXZhbCA9IFRSVUUsIGVjaG8gPSBUUlVFfQ0KDQojLS0tUFJFUEFSQUNJT04gREUgTE9TIERBVE9TDQp0aWVtcG9zIDwtIHJpbzo6aW1wb3J0KGZpbGUgPSAiLi9kYXRvcy9sYXBfdGltZXMuY3N2IikNCnBpbG90b3MgPC0gcmlvOjppbXBvcnQoZmlsZSA9ICIuL2RhdG9zL2RyaXZlcnMuY3N2IikNCnJlc3VsdGFkb3MgPC0gcmlvOjppbXBvcnQoZmlsZSA9ICIuL2RhdG9zL3Jlc3VsdHMuY3N2IikNCmNhcnJlcmFzIDwtIHJpbzo6aW1wb3J0KGZpbGUgPSAiLi9kYXRvcy9yYWNlcy5jc3YiKQ0KZXNjdWRlcmlhcyA8LSByaW86OmltcG9ydChmaWxlID0gIi4vZGF0b3MvY29uc3RydWN0b3JzLmNzdiIpDQplc2N1ZGVyaWFzMiA8LSByaW86OmltcG9ydChmaWxlID0gIi4vZGF0b3MvY29uc3RydWN0b3Jfc3RhbmRpbmdzLmNzdiIpDQpyZXN1bHRfZXNjdWRlcmlhcyA8LSByaW86OmltcG9ydChmaWxlID0gIi4vZGF0b3MvY29uc3RydWN0b3JfcmVzdWx0cy5jc3YiKQ0KY2lyY3VpdG9zIDwtIHJpbzo6aW1wb3J0KGZpbGUgPSAiLi9kYXRvcy9jaXJjdWl0cy5jc3YiKQ0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KI2NhcGl0dWxvIG9zY3VybyBkZWwgZGVwb3J0ZQ0KI2NyZW8gZGYgZGUgbXVlcnRlcyBkZSBmb3JtdWxhIDENCm11ZXJ0ZXNmMSA8LSBkYXRhLmZyYW1lKA0KICAib3JkZW4iID0gMTo0MiwNCiAgImRyaXZlclJlZiIgPSBjKCJDaGV0IE1pbGxlciIsICJDYXJsIFNjYXJhYm9yb3VnaCIsICJPbm9mcmUgTWFyaW1vbiIsICJNYW5ueSBBeXVsbyIsICJCaWxsIFZ1a292aWNoIiwgIkFsYmVydG8gQXNjYXJpIiwiRXVnZW5pbyBDYXN0ZWxsb3R0aSIsICJLZWl0aCBBbmRyZXdzIiwgIlBhdCBPJ0Nvbm5vciIsICJMdWlnaSBNdXNzbyIsICJQZXRlciBDb2xsaW5zIiwgIlN0dWFydCBMZXdpcy1FdmFucyIsICJKZXJyeSBVbnNlciIsICJCb2IgQ29ydG5lciIsICJJdm9yIEJ1ZWIiLCAiQ2hyaXMgQnJpc3RvdyIsICJBbGFuIFN0YWNleSIsICJHaXVsaW8gQ2FiaWFuY2EiLCAiV29sZmdhbmcgdm9uIFRyaXBzIiwgIkNhcmVsIEdvZGluIGRlIEJlYXVmb3J0IiwgIkpvaG4gVGF5bG9yIiwgIkxvcmVuem8gQmFuZGluaSIsICJCb2IgQW5kZXJzb24iLCAiSm8gU2NobGVzc2VyIiwgIkdlcmhhcmQgTWl0dGVyIiwgIlBpZXJzIENvdXJhZ2UiLCAiSm9jaGVuIFJpbmR0IiwgIkpvIFNpZmZlcnQiLCAiUm9nZXIgV2lsbGlhbXNvbiIsICJGcmFuw6dvaXMgQ2V2ZXJ0IiwgIlBldGVyIFJldnNvbiIsICJIZWxtdXRoIEtvaW5pZ2ciLCAiTWFyayBEb25vaHVlIiwgIlRvbSBQcnljZSIsICJSb25uaWUgUGV0ZXJzb24iLCAiUGF0cmljayBEZXBhaWxsZXIiLCAiR2lsbGVzIFZpbGxlbmV1dmUiLCAiUmljY2FyZG8gUGFsZXR0aSIsICJFbGlvIGRlIEFuZ2VsaXMiLCAiUm9sYW5kIFJhdHplbmJlcmdlciIsICJBeXJ0b24gU2VubmEiLCAiSnVsZXMgQmlhbmNoaSIpLA0KICAibmF0aW9uYWxpdHkiID0gYygiQW1lcmljYW4iLCAiQW1lcmljYW4iLCAiQXJnZW50aW5lIiwgIkFtZXJpY2FuIiwgIkFtZXJpY2FuIiwgIkl0YWxpYW4iLCJJdGFsaWFuIiwgIkFtZXJpY2FuIiwgIkFtZXJpY2FuIiwgIkl0YWxpYW4iLCAiQnJpdGlzaCIsICJCcml0aXNoIiwgIkFtZXJpY2FuIiwgIkFtZXJpY2FuIiwgIkJyaXRpc2giLCAiQnJpdGlzaCIsICJCcml0aXNoIiwgIkl0YWxpYW4iLCAiR2VybWFuIiwgIkR1dGNoIiwgIkJyaXRpc2giLCAiSXRhbGlhbiIgLCAiQnJpdGlzaCIsICJGcmVuY2giLCAiR2VybWFuIiwgIkJyaXRpc2giLCAiQXVzdHJpYW4iLCAiU3dpc3MiLCAiQnJpdGlzaCIsICJGcmVuY2giLCAiQW1lcmljYW4iLCAiQXVzdHJpYW4iLCAiQW1lcmljYW4iLCAiQnJpdGlzaCIsICJTd2VkaXNoIiwgIkZyZW5jaCIsICJDYW5hZGlhbiIsICJJdGFsaWFuIiwgIkl0YWxpYW4iLCAiQXVzdHJpYW4iLCAiQnJhemlsaWFuIiwgIkZyZW5jaCIpLA0KICAiZmVjaGFfbXVlcnRlIiA9IGMoMTk1MywgMTk1MywgMTk1NCwgMTk1NSwgMTk1NSwgMTk1NSwgMTk1NywgMTk1NywgMTk1OCwxOTU4LDE5NTgsMTk1OCwxOTU5LDE5NTksMTk1OSwxOTYwLCAxOTYwLDE5NjEsMTk2MSwxOTY0LDE5NjYsIDE5NjcsIDE5NjcsMTk2OCwxOTY5LCAxOTcwLDE5NzAsMTk3MSwxOTczLDE5NzMsMTk3NCwxOTc0LDE5NzUsMTk3NywxOTc4LDE5ODAsMTk4MiwxOTgyLDE5ODYsMTk5NCwxOTk0LDIwMTQpKQ0KI25vIHBvbmdvIGxhcyBjb21pbGxhcyBlbiBsb3MgYcOxb3MgcGFyYSBxdWUgc2UgY3JlZW4gZGlyZWN0YW1lbnRlIGNvbW8gb2JzZXJ2YWNpb25lcyBudW1lcmljYXMNCg0KI2NyZW8gdW4gZGYgY29uIHRvZG9zIGxvcyBhw7FvcyBwYXJhIGx1ZWdvIGZ1c2lvbmFybG8sIHlhIHF1ZSBubyBoYXkgbXVlcnRlcyB0b2RvcyBsb3MgYcOxb3MgDQphbnlvcyA8LSBkYXRhLmZyYW1lKA0KICAib3JkZW4iID0gMTo3MSwNCiAgImHDsW8iID0gYygxOTUwOjIwMjApKQ0KDQojc3VtYXRvcmlvIGRlIGxhcyBtdWVydGVzIHBvciBhw7FvDQptdWVydGVzX2FueW8gPC0gbXVlcnRlc2YxICU+JSBncm91cF9ieShmZWNoYV9tdWVydGUpICU+JSBtdXRhdGUobXVlcnRlc3hhbnlvID0gc3VtKG4oKSkpICU+JSBkaXN0aW5jdChmZWNoYV9tdWVydGUsIG11ZXJ0ZXN4YW55bykgDQoNCiNmdXNpb25vIGxvcyAyIGRmcyBwYXJhIHF1ZSB0ZW5nYSBlbiBjdWVudGEgbG9zIGHDsW9zIGRvbmRlIG5vIGhheSBtdWVydGVzDQptdWVydGVzZjFfZmluYWwgPC0gZnVsbF9qb2luKG11ZXJ0ZXNfYW55bywgYW55b3MsIGMoImZlY2hhX211ZXJ0ZSIgPSAiYcOxbyIpKSAlPiUgc2VsZWN0KGZlY2hhX211ZXJ0ZSxtdWVydGVzeGFueW8pICU+JSBhcnJhbmdlKGZlY2hhX211ZXJ0ZSkNCg0KI2NvbnZpZXJ0byBsb3MgTi9BIGVuIDAsIGVzIGRlY2lyLCBjdWFuZG8gbm8gaGF5IG9ic2VydmFjaW9uZXMsIGhhIGhhYmlkbyAwIG11ZXJ0ZXMNCm11ZXJ0ZXNmMV9maW5hbFtpcy5uYShtdWVydGVzZjFfZmluYWwpXSA8LSAwDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiNzdHIocmVzdWx0YWRvcykNCiNzdHIocGlsb3RvcykNCiNwaWxvdG9zWywgYygxKV0gPC0gc2FwcGx5KHBpbG90b3NbLCBjKDEpXSwgYXMubnVtZXJpYykNCiNyZXN1bHRhZG9zWywgYygzLDYsOSldIDwtIHNhcHBseShyZXN1bHRhZG9zWywgYygzLDYsOSldLCBhcy5udW1lcmljKQ0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojbnVtZXJvIGRlIGNhcnJlcmFzIHF1ZSBoYSBjb3JyaWRvIGNhZGEgcGlsb3RvDQoNCm5fY2FycmVyYXMgPC0gcmVzdWx0YWRvcyAlPiUgZ3JvdXBfYnkoZHJpdmVySWQpICU+JSBtdXRhdGUobnVtZXJvX2NhcnJlcmFzID0gc3VtKG4oKSkpICU+JSBkaXN0aW5jdChudW1lcm9fY2FycmVyYXMpICU+JSBhcnJhbmdlKGRlc2MobnVtZXJvX2NhcnJlcmFzKSkgDQoNCm5fY2FycmVyYXNfbm9tIDwtIGZ1bGxfam9pbihuX2NhcnJlcmFzLCBwaWxvdG9zLCBjICgiZHJpdmVySWQiID0gImRyaXZlcklkIikpICU+JSBzZWxlY3QoZHJpdmVySWQsIGRyaXZlclJlZiwgbnVtZXJvX2NhcnJlcmFzKSAgJT4lICBmaWx0ZXIobnVtZXJvX2NhcnJlcmFzID49IDIwMiApICNsb3MgMjAgcXF1ZSBtYXMgY2FycmVyYXMgdGllbmVuIChubyBmdW5jaW9uYSB1c2FyIHNsaWNlX21heCkNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojbmFjaW9uYWxpZGFkIGRlIGxvcyBwaWxvdG9zIGEgbG8gbGFyZ28gZGUgbGEgaGlzdG9yaWEgDQojbWFwYQ0KbmFjaW9uYWxpZGFkIDwtIHBpbG90b3MgJT4lIGdyb3VwX2J5KG5hdGlvbmFsaXR5KSAlPiUgbXV0YXRlKG51bWVyb19jb21wYXRyaW90YXMgPSBzdW0obigpKSkgJT4lIGRpc3RpbmN0KG51bWVyb19jb21wYXRyaW90YXMpICU+JSBhcnJhbmdlKGRlc2MobnVtZXJvX2NvbXBhdHJpb3RhcykpICU+JSANCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJCcml0aXNoIiwgIlVuaXRlZCBLaW5nZG9tIikgJT4lIA0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIkFtZXJpY2FuIiwgIlVuaXRlZCBTdGF0ZXMiKSAlPiUgDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiSXRhbGlhbiIsICdJdGFseScpICU+JSANCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJGcmVuY2giICwgJ0ZyYW5jZScpICU+JSANCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJHZXJtYW4iICwgJ0dlcm1hbnknKSAlPiUgDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiQnJhemlsaWFuIiAsICdCcmF6aWwnKSAlPiUgDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiQXJnZW50aW5lIiAsICdBcmdlbnRpbmEnKSAlPiUgDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiU3dpc3MiICwgJ1N3aXR6ZXJsYW5kJykgJT4lIA0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIkJlbGdpYW4iICwgJ0JlbGdpdW0nKSAlPiUgDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiU291dGggQWZyaWNhbiIgLCAnU291dGggQWZyaWNhJykgJT4lIA0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIkphcGFuZXNlIiAsICdKYXBhbicpICU+JSANCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJBdXN0cmFsaWFuIiAsICdBdXN0cmFsaWEnKSAlPiUNCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJEdXRjaCIgLCAnTmV0aGVybGFuZHMnKSAlPiUNCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJTcGFuaXNoIiAsICdTcGFpbicpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIkF1c3RyaWFuIiAsICdBdXN0cmlhJykgJT4lDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiQ2FuYWRpYW4iICwgJ0NhbmFkYScpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIlN3ZWRpc2giICwgJ1N3ZWRlbicpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIkZpbm5pc2giICwgJ0ZpbmxhbmQnKSAlPiUNCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJOZXcgWmVhbGFuZGVyIiAsICdOZXcgWmVhbGFuZCcpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIk1leGljYW4iICwgJ01leGljbycpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIklyaXNoIiAsICdJcmVsYW5kJykgJT4lDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiRGFuaXNoIiAsICdEZW5tYXJrJykgJT4lDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiUG9ydHVndWVzZSIgLCAnUG9ydHVnYWwnKSAlPiUNCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJNb25lZ2FzcXVlIiAsICdGcmFuY2UnKSAlPiUNCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJSaG9kZXNpYW4iICwgJ1ppbWJhYndlJykgJT4lDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiVXJ1Z3VheWFuIiAsICdVcnVndWF5JykgJT4lDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiUnVzc2lhbiIgLCAnUnVzc2lhJykgJT4lDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiQ29sb21iaWFuIiAsICdDb2xvbWJpYScpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIlZlbmV6dWVsYW4iICwgJ1ZlbmV6dWVsYScpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIkVhc3QgR2VybWFuIiAsICdHZXJtYW4nKSAlPiUNCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJJbmRpYW4iICwgJ0luZGlhJykgJT4lDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiVGhhaSIgLCAnVGhhaWxhbmQnKSAlPiUNCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJQb2xpc2giICwgJ1BvbGFuZCcpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIk1vbmVnYXNxdWUiICwgJ0ZyYW5jZScpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIkh1bmdhcmlhbiIgLCAnSHVuZ2FyeScpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIkN6ZWNoIiAsICdDemVjaCBSZXAuJykgJT4lDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiTWFsYXlzaWFuIiAsICdNYWxheXNpYScpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIkNoaWxlYW4iICwgJ0NoaWxlJykgJT4lDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiTGllY2h0ZW5zdGVpbmVyIiAsICdTd2l0emVybGFuZCcpICU+JQ0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIkFtZXJpY2FuLUl0YWxpYW4iICwgJ1VuaXRlZCBTdGF0ZXMnKSAlPiUNCiAgc3RyX3JlcGxhY2VfYWxsKC4sICJBcmdlbnRpbmUtSXRhbGlhbiIgLCAnQXJnZW50aW5hJykgJT4lDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiSW5kb25lc2lhbiIgLCAnSW5kb25lc2lhJykNCg0KcGFpc2VzX25vcm1hbGVzIDwtIGMoIlVuaXRlZCBLaW5nZG9tIiwgIlVuaXRlZCBTdGF0ZXMiLCAiSXRhbHkiLCAiRnJhbmNlIiwgIkdlcm1hbnkiLCAiQnJhemlsIiwgIkFyZ2VudGluYSIsICJTd2l0emVybGFuZCIsICJCZWxnaXVtIiwgIlNvdXRoIEFmcmljYSIsICJKYXBhbiIsICJBdXN0cmFsaWEiLCAiTmV0aGVybGFuZHMiLCAiU3BhaW4iLCAiQXVzdHJpYSIsICJDYW5hZGEiLCAiU3dlZGVuIiwgIkZpbmxhbmQiLCAiTmV3IFplYWxhbmQiLCAiTWV4aWNvIiwgIklyZWxhbmQiLCAiRGVubWFyayIsICJQb3J0dWdhbCIsICJGcmFuY2UiLCAiWmltYmFid2UiLCAiVXJ1Z3VheSIsICJSdXNzaWEiLCAiQ29sb21iaWEiLCAiVmVuZXp1ZWxhIiwgIkdlcm1hbnkiLCAiSW5kaWEiLCAiVGhhaWxhbmQiLCAiUG9sYW5kIiwgIkh1bmdhcnkiLCAiQ3plY2ggUmVwLiIsICJNYWxheXNpYSIsICJDaGlsZSIsICJTd2l0emVybGFuZCIsICJVbml0ZWQgU3RhdGVzIiwgIkFyZ2VudGluYSIsICJJbmRvbmVzaWEiICkNCg0KbmFjaW9uYWxpZGFkIDwtIHBpbG90b3MgJT4lIGdyb3VwX2J5KG5hdGlvbmFsaXR5KSAlPiUgDQogIG11dGF0ZShudW1lcm9fY29tcGF0cmlvdGFzID0gc3VtKG4oKSkpICU+JSANCiAgZGlzdGluY3QobnVtZXJvX2NvbXBhdHJpb3RhcykgJT4lIA0KICBhcnJhbmdlKGRlc2MobnVtZXJvX2NvbXBhdHJpb3RhcykpICU+JSANCiAgYWRkX2NvbHVtbihwYWlzZXNfbm9ybWFsZXMpICU+JSAgDQogIGdyb3VwX2J5KHBhaXNlc19ub3JtYWxlcykgJT4lIA0KICBtdXRhdGUodG90YWxfcGlsb3RvcyA9IHN1bShudW1lcm9fY29tcGF0cmlvdGFzKSkgJT4lICANCiAgZGlzdGluY3QocGFpc2VzX25vcm1hbGVzLCB0b3RhbF9waWxvdG9zKQ0KDQpkYXRhKFdvcmxkKQ0Kd29ybGQgPC0gV29ybGQ7IHJtKFdvcmxkKQ0KDQp3b3JsZCA8LSB3b3JsZFshKHdvcmxkJG5hbWUgJWluJSBjKCdHcmVlbmxhbmQnLCAnQW50YXJjdGljYScpKSxdDQoNCnBpbG90b3NfcG9yX3BhaXNlcyA8LSBmdWxsX2pvaW4obmFjaW9uYWxpZGFkLCB3b3JsZCwgYyggInBhaXNlc19ub3JtYWxlcyIgPSAibmFtZSIpKSANCg0KcGlsb3Rvc19wb3JfcGFpc2VzJGNvdW50cnkgPC0gTlVMTA0KDQpwaWxvdG9zX3Bvcl9wYWlzZXNbaXMubmEocGlsb3Rvc19wb3JfcGFpc2VzKV0gPC0gMA0KDQpnZ19waWxvdG9zX3Bvcl9wYWlzZXMgPC0gZ2dwbG90KGRhdGEgPSBwaWxvdG9zX3Bvcl9wYWlzZXMsIGFlcyhnZW9tZXRyeSA9IGdlb21ldHJ5KSkgKyBnZW9tX3NmKCkgKw0KICAgICAgIGxhYnModGl0bGUgPSAiUGlsb3RvcyBwb3IgcGHDrXMiLA0KICAgICAgICAgICAgY2FwdGlvbiA9ICJNZW5vciBpbnRlbnNpZGFkIGRlIGNvbG9yIGVuIGFxdWVsbG9zIHBhaXNlcyBjb24gbcOhcyBwaWxvdG9zIikNCg0KZ2dfcGlsb3Rvc19wb3JfcGFpc2VzIDwtIGdnX3BpbG90b3NfcG9yX3BhaXNlcyArIA0KICBnZW9tX3NmKGFlcyhmaWxsID0gdG90YWxfcGlsb3RvcykpICsgDQogIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3VyID0gIndoaXRlIiksDQogICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJ3aGl0ZSIpLA0KICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUobGluZXR5cGUgPSAiYmxhbmsiKSwNCiAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGxpbmV0eXBlID0gImJsYW5rIiksDQogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJibGFuayIpLA0KICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAiZ3JheTEzIiksDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsDQogICAgICAgIGNvbG91ciA9ICJ3aGl0ZSIsIGhqdXN0ID0gMC41KSwgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gIndoaXRlIiksDQogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJ3aGl0ZSIpLA0KICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiKSwNCiAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiKSwNCiAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXkxMyIpKSArbGFicyhmaWxsID0gIk7CqiBkZSBwaWxvdG9zIikgKyB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJncmF5MTMiKSwNCiAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImdyYXkxMyIpKSArIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gTkEpLA0KICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QobGluZXR5cGUgPSAic29saWQiKSwNCiAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QobGluZXR5cGUgPSAic29saWQiKSkgKyBzY2FsZV9maWxsX2dyYWRpZW50Mihsb3cgPSAid2hpdGUiLCBtaWQgPSAicGluayIsIGhpZ2ggPSAicmVkIiwgbWlkcG9pbnQgPSAuMDIpDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgbnVtZXJvIGRlIHZpY3RvcmlhcyBwb3IgcGlsb3RvDQp2aWN0b3JpYXMgPC0gcmVzdWx0YWRvcyAlPiUgZmlsdGVyKHBvc2l0aW9uID09ICIxIikgJT4lIA0KICBncm91cF9ieShkcml2ZXJJZCkgJT4lIA0KICBtdXRhdGUobl92aWN0b3JpYXMgPSBzdW0obigpKSkgJT4lIA0KICBkaXN0aW5jdChuX3ZpY3RvcmlhcykgJT4lIA0KICBhcnJhbmdlKGRlc2Mobl92aWN0b3JpYXMpKQ0KDQojYXF1aSBmdXNpb25vIGNvbiBlbCBkZiBkZSBwaWxvdG9zIHBhcmEgcXVlIGFwYXJlemNhIGVsIG5vbWJyZSB5IG5vIHPDs2xvIGVsIElEIGRlbCBwaWxvdG8gZW4gY3Vlc3Rpb24sIHkgaGFnbyBsbyBtaXNtbyBxdWUgZW4gZWwgYXBhcnRhZG8gZGUgYXJyaWJhIHBhcmEgb3JkZW5hcg0KdmljdG9yaWFzX2Nvbl9ub21icmUgPC0gZnVsbF9qb2luKHZpY3RvcmlhcywgcGlsb3RvcywgYyAoImRyaXZlcklkIiA9ICJkcml2ZXJJZCIpKSAlPiUgDQogIHNlbGVjdChkcml2ZXJJZCwgbmF0aW9uYWxpdHksIGRyaXZlclJlZiwgbl92aWN0b3JpYXMpICANCm1hc192aWN0b3JpYXMgPC0gdmljdG9yaWFzX2Nvbl9ub21icmUgJT4lICBmaWx0ZXIobl92aWN0b3JpYXMgPj0gMjUgKSANCg0KI3ZpY3RvcmlhcyAyDQp2aWN0b3JpYXMyIDwtIGZ1bGxfam9pbihwaWxvdG9zLCByZXN1bHRhZG9zLCBjKCJkcml2ZXJJZCIgPSAiZHJpdmVySWQiKSkgJT4lIA0KICBmdWxsX2pvaW4oLiwgY2FycmVyYXMsIGMoInJhY2VJZCIgPSAicmFjZUlkIikpICU+JSANCiAgc2VsZWN0KGRyaXZlcklkLCBkcml2ZXJSZWYsIHBvc2l0aW9uLCB5ZWFyLCBkYXRlKSAlPiUgDQogIGZpbHRlcihwb3NpdGlvbiA9PSAxKSAlPiUgDQogIGdyb3VwX2J5KGRyaXZlclJlZikgJT4lIA0KICBtdXRhdGUodmljdG9yaWFfbnVtID0gc3VtKCBOTiA9IG4oKSkpICU+JSANCiAgZmlsdGVyKHZpY3RvcmlhX251bSA+PSAyMCkgJT4lIA0KICBhcnJhbmdlKHZpY3RvcmlhX251bSwgZGF0ZSkgJT4lIA0KICBtdXRhdGUoIHN1bWFfdmljID0gY3Vtc3VtKHBvc2l0aW9uKSkNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KI3Jlc3VsdGFkbyBtZWRpbw0KDQpyZXN1bHRhZG9zWywgYyg3KV0gPC0gc2FwcGx5KHJlc3VsdGFkb3NbLCBjKDcpXSwgYXMubnVtZXJpYykNCnJlc3VsdGFkb3NbaXMubmEocmVzdWx0YWRvcyldIDwtIDI1IA0KDQojcmVzdWx0YWRvX21lZGlvIDwtICBmdWxsX2pvaW4ocGlsb3RvcywgcmVzdWx0YWRvcywgIGMgKCJkcml2ZXJJZCIgPSAiZHJpdmVySWQiKSkgJT4lIA0KI3NlbGVjdChkcml2ZXJJZCwgZHJpdmVyUmVmLCBwb3NpdGlvbikgJT4lIA0KICMgZ3JvdXBfYnkoZHJpdmVySWQpICU+JSANCiAgI211dGF0ZShyZXN1bHRfbWVkaW8gPSBtZWFuKHBvc2l0aW9uKSkgJT4lIA0KICAjZGlzdGluY3QgKGRyaXZlcklkLCBkcml2ZXJSZWYsIHJlc3VsdF9tZWRpbykgJT4lIGFycmFuZ2UocmVzdWx0X21lZGlvKQ0KDQojcmVzdWx0YWRvIG1lZGlvIGVuIGNsYXNpZmljYWNpb24NCnJlc3VsdGFkb19tZWRpb19jbGFzIDwtICBmdWxsX2pvaW4ocGlsb3RvcywgcmVzdWx0YWRvcywgIGMgKCJkcml2ZXJJZCIgPSAiZHJpdmVySWQiKSkgJT4lIA0KICBzZWxlY3QoZHJpdmVySWQsIGRyaXZlclJlZiwgZ3JpZCkgJT4lIA0KICBncm91cF9ieShkcml2ZXJJZCkgJT4lIA0KICBtdXRhdGUocmVzdWx0X21lZGlvX2NsYXMgPSBtZWFuKGdyaWQpKSAlPiUgDQogIGRpc3RpbmN0IChkcml2ZXJJZCwgZHJpdmVyUmVmLCByZXN1bHRfbWVkaW9fY2xhcykgICU+JSANCiAgZmlsdGVyKHJlc3VsdF9tZWRpb19jbGFzID4gMCkgJT4lIA0KICBhcnJhbmdlKHJlc3VsdF9tZWRpb19jbGFzKSAgDQoNCg0KI251bWVybyBkZSB2dWVsdGFzIGxpZGVyYW5kbw0KDQoNCiNwdW50b3MgcG9yIGNhcnJlcmEgKHB1bnRvcy9jYXJyZXJhKQ0KDQpwdW50b3NfeF9jYXJyZXJhIDwtICBmdWxsX2pvaW4ocGlsb3RvcywgcmVzdWx0YWRvcywgIGMgKCJkcml2ZXJJZCIgPSAiZHJpdmVySWQiKSkgJT4lIHNlbGVjdChkcml2ZXJJZCwgZHJpdmVyUmVmLCBwb2ludHMpICU+JSBmdWxsX2pvaW4oLiwgbl9jYXJyZXJhcywgIGMgKCJkcml2ZXJJZCIgPSAiZHJpdmVySWQiKSkgJT4lIGdyb3VwX2J5KGRyaXZlcklkKSAlPiUgbXV0YXRlKHRvdGFsX3B1bnRvcyA9IHN1bShwb2ludHMpKSAlPiUgZGlzdGluY3QoZHJpdmVySWQsIGRyaXZlclJlZiwgbnVtZXJvX2NhcnJlcmFzLCB0b3RhbF9wdW50b3MpICU+JSBtdXRhdGUobWVkaWFfcHVudG9zID0gdG90YWxfcHVudG9zL251bWVyb19jYXJyZXJhcykgJT4lIGFycmFuZ2UoZGVzYyhtZWRpYV9wdW50b3MpKQ0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KI3JlbW9udGFkYXMNCg0KI21hcyBwb3NpY2lvbmVzIHJlbW9udGFkYXMgZW4gdW5hIGNhcnJlcmEgZ3JhbiBwcmVtaW8NCg0KDQpyZXN1bHRhZG9zWywgYyg2LDkpXSA8LSBzYXBwbHkocmVzdWx0YWRvc1ssIGMoNiw5KV0sIGFzLm51bWVyaWMpICN0cmFuc2Zvcm1vIHZhcmlhYmxlcyBncmlkIHkgcG9zaXRpb25PcmRlciBlbiBudW1lcmljbw0Kc3RyKHJlc3VsdGFkb3MpICMgcGFyYSBjb21wcm9iYXJsbw0KDQoNCiNtYXlvcmVzIHJlbW9udGFkYXMgZGUgbGEgaGlzdG9yaWEsIHNlIHJlc3RhIHBvc2ljaW9uIGRlIHNhbGlkYSAtIHBvc2ljaW9uIGZpbmFsDQpwdWVzdG9zX3JlbW9udGFkb3MgPC0gcmVzdWx0YWRvcyAlPiUgbXV0YXRlKHJlbW9udGFkb3MgPSBncmlkIC0gcG9zaXRpb25PcmRlcikgJT4lIA0KICBzZWxlY3QocmFjZUlkLCBkcml2ZXJJZCwgZ3JpZCwgcG9zaXRpb25PcmRlciwgcmVtb250YWRvcykgDQoNCg0KI2RlIHRvZGEgbGEgaGlzdG9yaWENCmNpcmN1aXRvc19ncCA8LSBmdWxsX2pvaW4oY2FycmVyYXMsIGNpcmN1aXRvcywgYygiY2lyY3VpdElkIiA9ICJjaXJjdWl0SWQiKSkgJT4lIA0KICBzZWxlY3QoY2lyY3VpdElkLCBuYW1lLnksIHJhY2VJZCwgeWVhcikNCg0KcHRvc19yZW1vbnRfY2FycmVyYSA8LSBpbm5lcl9qb2luKHB1ZXN0b3NfcmVtb250YWRvcywgY2lyY3VpdG9zX2dwKQ0KDQpwdWVzdG9zX3JlbW9udF9waWxvdG8gPC0gZnVsbF9qb2luKHBpbG90b3MsIHB0b3NfcmVtb250X2NhcnJlcmEsIGMoImRyaXZlcklkIiA9ICJkcml2ZXJJZCIpKSAlPiUgDQogIHNsaWNlX21heChyZW1vbnRhZG9zLCBuPTEwKSAlPiUgDQogIHNlbGVjdChkcml2ZXJJZCwgZHJpdmVyUmVmLG5hbWUueSx5ZWFyLCByYWNlSWQsIGdyaWQsIHBvc2l0aW9uT3JkZXIsIHJlbW9udGFkb3MpDQoNCiMgZGUgbGEgaGlzb3RvcmlhIHJlY2llbnRlDQpjaXJjdWl0b3NfZ3BfcmVjaWVudCA8LSBmdWxsX2pvaW4oY2FycmVyYXMsIGNpcmN1aXRvcywgYygiY2lyY3VpdElkIiA9ICJjaXJjdWl0SWQiKSkgJT4lIA0KICBzZWxlY3QoY2lyY3VpdElkLCBuYW1lLnksIHJhY2VJZCwgeWVhcikgJT4lIA0KICBmaWx0ZXIoeWVhciA+PSAxOTk1KQ0KDQpwdG9zX3JlbW9udF9jYXJyZXJhX3JlY2llbnQgPC0gaW5uZXJfam9pbihwdWVzdG9zX3JlbW9udGFkb3MsIGNpcmN1aXRvc19ncF9yZWNpZW50KQ0KDQpwdWVzdG9zX3JlbW9udF9waWxvdG9fcmVjaWVudCA8LSBmdWxsX2pvaW4ocGlsb3RvcywgcHRvc19yZW1vbnRfY2FycmVyYV9yZWNpZW50LCBjKCJkcml2ZXJJZCIgPSAiZHJpdmVySWQiKSkgJT4lIA0KICBzbGljZV9tYXgocmVtb250YWRvcywgbj0xMCkgJT4lIA0KICBzZWxlY3QoZHJpdmVySWQsIGRyaXZlclJlZiwgbmFtZS55LCB5ZWFyLHJhY2VJZCwgZ3JpZCwgcG9zaXRpb25PcmRlciwgcmVtb250YWRvcykgJT4lIA0KICBzbGljZSgxOjQsNjo4LDEwKSAlPiUgDQogIGFycmFuZ2UoZGVzYyhyZW1vbnRhZG9zKSkNCg0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiNtdW5kaWFsZXMgcG9yIG5haW9uYWxpZGFkIHkgcGlsb3RvDQpjYW1wZW9uZXMgPC0gZnVsbF9qb2luKHBpbG90b3MsIHJlc3VsdGFkb3MsIGMoImRyaXZlcklkIiA9ICJkcml2ZXJJZCIpKSAlPiUgDQogIGZ1bGxfam9pbiguLCBjYXJyZXJhcywgYygicmFjZUlkIiA9ICJyYWNlSWQiKSkgJT4lIA0KICBzZWxlY3QoZHJpdmVySWQsIGRyaXZlclJlZiwgbmF0aW9uYWxpdHksIGNvbnN0cnVjdG9ySWQsIHBvaW50cywgeWVhciwgcm91bmQpICU+JSANCiAgZnVsbF9qb2luKC4sIGVzY3VkZXJpYXMsIGMoImNvbnN0cnVjdG9ySWQiID0gImNvbnN0cnVjdG9ySWQiKSkgJT4lIA0KICBzZWxlY3QoZHJpdmVySWQsIGRyaXZlclJlZiwgbmF0aW9uYWxpdHkueCwgY29uc3RydWN0b3JJZCwgcG9pbnRzLCB5ZWFyLCBuYW1lLCByb3VuZCkgJT4lICANCiAgZ3JvdXBfYnkoeWVhciwgZHJpdmVyUmVmKSAlPiUgIA0KICBtdXRhdGUocHVudG9zX3RvdGFsZXMgPSBjdW1zdW0ocG9pbnRzKSkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBncm91cF9ieSh5ZWFyKSAlPiUgDQogIHNsaWNlX21heChwdW50b3NfdG90YWxlcywgbj0xKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgZ3JvdXBfYnkoZHJpdmVyUmVmKSAlPiUgDQogIG11dGF0ZSh0b3RhbF9jYW1wZW9uYXRvcyA9IHN1bShOTiA9IG4oKSkpICU+JSANCiAgZGlzdGluY3QoZHJpdmVyUmVmLCBuYXRpb25hbGl0eS54LCB0b3RhbF9jYW1wZW9uYXRvcykgJT4lIA0KICBhcnJhbmdlKG5hdGlvbmFsaXR5LngsIHRvdGFsX2NhbXBlb25hdG9zKQ0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KI3RlbXBvcmFkYSAyMDIxIHRhYmxhDQoNCnBpbG90b3NfMjAyMSA8LSBmdWxsX2pvaW4oY2FycmVyYXMsIHJlc3VsdGFkb3MsIGMoInJhY2VJZCIgPSAicmFjZUlkIikgKSAlPiUgDQogIGZ1bGxfam9pbiguLHBpbG90b3MsIGMoImRyaXZlcklkIj0iZHJpdmVySWQiKSkgJT4lIA0KICBmaWx0ZXIoeWVhcj09IjIwMjEiKSAlPiUgDQogIHNlbGVjdChmb3JlbmFtZSxzdXJuYW1lLCB5ZWFyKSAlPiUgDQogIGRpc3RpbmN0KGZvcmVuYW1lLHN1cm5hbWUpICU+JSANCiAgbmEub21pdCgpICU+JSANCiAgYXJyYW5nZShzdXJuYW1lKSAlPiUgDQogIHN0cl9yZXBsYWNlX2FsbCguLCAiw4PCqSIsICLDqSIpICU+JSANCiAgc3RyX3JlcGxhY2VfYWxsKC4sICLDg8KkIiwgIsOkIikgJT4lIA0KICBzdHJfcmVwbGFjZV9hbGwoLiwgIsODwrYiLCAiw7YiKQ0KDQpub21icmVzX25vcm1hbGVzIDwtIGMoIkFsb25zbyIsICJCb3R0YXMiLCAiR2FzbHkiLCAiR2lvdmluYXp6aSIsICJIYW1pbHRvbiIsICJMYXRpZmkiLCAiTGVjbGVyYyIsICJNYXplcGluIiwgIk5vcnJpcyIsICJPY29uIiwgIlDDqXJleiIsICJSw6Rpa2vDtm5lbiIsICJSaWNjaWFyZG8iLCAiUnVzc2VsbCIsICJTYWlueiIsICJTY2h1bWFjaGVyIiwgIlN0cm9sbCIsICJUc3Vub2RhIiwgIlZlcnN0YXBwZW4iLCAiVmV0dGVsIikNCg0KcGlsb3Rvc18yMDIxIDwtICBmdWxsX2pvaW4oY2FycmVyYXMsIHJlc3VsdGFkb3MsIGMoInJhY2VJZCIgPSAicmFjZUlkIikgKSAlPiUgDQogIGZ1bGxfam9pbiguLHBpbG90b3MsIGMoImRyaXZlcklkIj0iZHJpdmVySWQiKSkgJT4lIA0KICBmaWx0ZXIoeWVhcj09IjIwMjEiKSAlPiUgDQogIHNlbGVjdChmb3JlbmFtZSxzdXJuYW1lLCB5ZWFyKSAlPiUgDQogIGRpc3RpbmN0KGZvcmVuYW1lLHN1cm5hbWUpICU+JSANCiAgbmEub21pdCgpICU+JSANCiAgYXJyYW5nZShzdXJuYW1lKSAlPiUgDQogIGFkZF9jb2x1bW4obm9tYnJlc19ub3JtYWxlcykgDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KI3RlbXBvcmFkYSAyMDIxIHRlbXBsb3MNCg0KY2FycmVyYXNfMjEgPC0gZnVsbF9qb2luKGNhcnJlcmFzLGNpcmN1aXRvcywgYygiY2lyY3VpdElkIiA9ICJjaXJjdWl0SWQiKSkgJT4lDQogIGZpbHRlcih5ZWFyPT0iMjAyMSIpICU+JQ0KICBzZWxlY3Qocm91bmQsIG5hbWUueCwgbmFtZS55LCBkYXRlLCBsb2NhdGlvbixjb3VudHJ5LCBsYXQsIGxuZywgYWx0KSAlPiUNCiAgYXJyYW5nZShyb3VuZCkgJT4lIA0KICBtdXRhdGUocm91bmQyID0gcm91bmQpIA0KDQpjYXJyZXJhc18yMV92MiA8LSBjYXJyZXJhc18yMVssIGMoMSwgNCwgMTAsIDIsIDMsIDUsIDYsIDcsIDgsIDkpXQ0KY2FycmVyYXNfMjFfdjIgPC0gY2FycmVyYXNfMjFfdjIlPiUgIHVuaXRlKC4gLHZhcmlhYmxlcywgYygxLCA1LCA3KSwgc2VwID0gIjsgIikNCg0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KI2VsIG5hbm8gY29udHJhIHRvZG9zDQoNCg0KYWxvdnNhbGwgPC0gZnVsbF9qb2luKHBpbG90b3MsIHJlc3VsdGFkb3MsIGMgKCJkcml2ZXJJZCIgPSAiZHJpdmVySWQiKSkgJT4lICANCiAgc2VsZWN0KGRyaXZlclJlZiwgcmVzdWx0SWQsIHJhY2VJZCwgY29uc3RydWN0b3JJZCwgcG9zaXRpb24sIHBvaW50cykgJT4lIA0KICBmdWxsX2pvaW4oLiwgZXNjdWRlcmlhcywgYyAoImNvbnN0cnVjdG9ySWQiID0gImNvbnN0cnVjdG9ySWQiKSkgJT4lIA0KICBzZWxlY3QoZHJpdmVyUmVmLCByZXN1bHRJZCwgcmFjZUlkLCBjb25zdHJ1Y3RvcklkLCBwb3NpdGlvbiwgcG9zaXRpb24sIHBvaW50cywgbmFtZSkgJT4lIA0KICBmdWxsX2pvaW4oLiwgY2FycmVyYXMsIGMgKCJyYWNlSWQiID0gInJhY2VJZCIpKSAlPiUgDQogIHNlbGVjdChkcml2ZXJSZWYsIHJlc3VsdElkLCByYWNlSWQsIGNvbnN0cnVjdG9ySWQsIHBvc2l0aW9uLCBwb3NpdGlvbiwgcG9pbnRzLCBuYW1lLngsIHllYXIsIHJvdW5kKQ0KDQojYWxvX3ZzX21hcnF1ZXMgPC0gYWxvdnNhbGwgJT4lIGZpbHRlcih5ZWFyID09IDIwMDEsIGRyaXZlclJlZiAlaW4lIGMoImFsb25zbyIsICJtYXJxdWVzIiksIHJvdW5kIDw9IDE0KQ0KDQphbG9fdnNfdHJ1bGxpIDwtIGFsb3ZzYWxsICU+JSBmaWx0ZXIoeWVhciAlaW4lIGMoMjAwMywgMjAwNCksIGRyaXZlclJlZiAlaW4lIGMoImFsb25zbyIsICJ0cnVsbGkiKSkgJT4lIHNsaWNlKDE6MTUsIDE3OjY3KSAlPiUgZ3JvdXBfYnkoZHJpdmVyUmVmLCB5ZWFyKSAlPiUgbXV0YXRlKHB1bnRvc19hY3VtdWxhZG9zID0gY3Vtc3VtKHBvaW50cykpICU+JSB1bmdyb3VwKCkNCg0KYWxvX3ZzX2Zpc2ljaGVsbGEgPC0gYWxvdnNhbGwgJT4lIGZpbHRlcih5ZWFyICVpbiUgYygyMDA1LCAyMDA2KSwgZHJpdmVyUmVmICVpbiUgYygiYWxvbnNvIiwgImZpc2ljaGVsbGEiKSkgICU+JSBncm91cF9ieShkcml2ZXJSZWYsIHllYXIpICU+JSBtdXRhdGUocHVudG9zX2FjdW11bGFkb3MgPSBjdW1zdW0ocG9pbnRzKSkgJT4lIHVuZ3JvdXAoKQ0KDQphbG9fdnNfaGFtaWx0b24gPC0gYWxvdnNhbGwgJT4lIGZpbHRlcih5ZWFyICVpbiUgYygyMDA3KSAsZHJpdmVyUmVmICVpbiUgYygiYWxvbnNvIiwgImhhbWlsdG9uIikpICAlPiUgZ3JvdXBfYnkoZHJpdmVyUmVmLCB5ZWFyKSAlPiUgbXV0YXRlKHB1bnRvc19hY3VtdWxhZG9zID0gY3Vtc3VtKHBvaW50cykpICU+JSB1bmdyb3VwKCkNCg0KYWxvX3ZzX3BpcXVldCA8LSBhbG92c2FsbCAlPiUgZmlsdGVyKHllYXIgJWluJSBjKDIwMDgsIDIwMDkpLCBkcml2ZXJSZWYgJWluJSBjKCJhbG9uc28iLCAicGlxdWV0X2pyIikpICU+JSBzbGljZSgxOjI4LCAzNjo2MykgJT4lIGdyb3VwX2J5KGRyaXZlclJlZiwgeWVhcikgJT4lIG11dGF0ZShwdW50b3NfYWN1bXVsYWRvcyA9IGN1bXN1bShwb2ludHMpKSAlPiUgdW5ncm91cCgpDQoNCiNhbG9fdnNfZ3Jvc2plYW4gPC0gYWxvdnNhbGwgJT4lIGZpbHRlcih5ZWFyID09IDIwMDksIGRyaXZlclJlZiAlaW4lIGMoImFsb25zbyIsICJncm9zamVhbiIpLCByb3VuZCA+PSAxMSkNCg0KYWxvX3ZzX21hc3NhIDwtIGFsb3ZzYWxsICU+JSBmaWx0ZXIoeWVhciAlaW4lIGMoMjAxMCwgMjAxMSwgMjAxMyksIGRyaXZlclJlZiAlaW4lIGMoImFsb25zbyIsICJtYXNzYSIpKSAlPiUgZ3JvdXBfYnkoZHJpdmVyUmVmLCB5ZWFyKSAlPiUgbXV0YXRlKHB1bnRvc19hY3VtdWxhZG9zID0gY3Vtc3VtKHBvaW50cykpICU+JSB1bmdyb3VwKCkNCg0KYWxvX3ZzX3JhaWtrb25lbiA8LSBhbG92c2FsbCAlPiUgZmlsdGVyKHllYXIgPT0gMjAxNCwgZHJpdmVyUmVmICVpbiUgYygiYWxvbnNvIiwgInJhaWtrb25lbiIpKSAlPiUgZ3JvdXBfYnkoZHJpdmVyUmVmLCB5ZWFyKSAlPiUgbXV0YXRlKHB1bnRvc19hY3VtdWxhZG9zID0gY3Vtc3VtKHBvaW50cykpICU+JSB1bmdyb3VwKCkNCg0KYWxvX3ZzX2J1dHRvbiA8LSBhbG92c2FsbCAlPiUgZmlsdGVyKHllYXIgJWluJSBjKDIwMTUsIDIwMTYpLCBkcml2ZXJSZWYgJWluJSBjKCJhbG9uc28iLCAiYnV0dG9uIikpICU+JSBncm91cF9ieShkcml2ZXJSZWYsIHllYXIpICU+JSBtdXRhdGUocHVudG9zX2FjdW11bGFkb3MgPSBjdW1zdW0ocG9pbnRzKSkgJT4lIHVuZ3JvdXAoKQ0KDQphbG9fdnNfdmFuZG9vcm5lIDwtIGFsb3ZzYWxsICU+JSBmaWx0ZXIoeWVhciAlaW4lIGMoMjAxNywgMjAxOCksIGRyaXZlclJlZiAlaW4lIGMoImFsb25zbyIsICJ2YW5kb29ybmUiKSkgJT4lIHNsaWNlKDE6NDUsIDQ3OjgxKSAlPiUgZ3JvdXBfYnkoZHJpdmVyUmVmLCB5ZWFyKSAlPiUgbXV0YXRlKHB1bnRvc19hY3VtdWxhZG9zID0gY3Vtc3VtKHBvaW50cykpJT4lIHVuZ3JvdXAoKSANCg0KYWxvX3ZzX29jb24gPC0gYWxvdnNhbGwgJT4lIGZpbHRlcih5ZWFyID09IDIwMjEsIGRyaXZlclJlZiAlaW4lIGMoImFsb25zbyIsICJvY29uIikpICU+JSBncm91cF9ieShkcml2ZXJSZWYsIHllYXIpICU+JSBtdXRhdGUocHVudG9zX2FjdW11bGFkb3MgPSBjdW1zdW0ocG9pbnRzKSkgJT4lIHVuZ3JvdXAoKQ0KDQpBTE9fVlNfQUxMIDwtIGZ1bGxfam9pbihhbG9fdnNfdHJ1bGxpLCBhbG9fdnNfZmlzaWNoZWxsYSwgYygiZHJpdmVyUmVmIj0gImRyaXZlclJlZiIsICJyZXN1bHRJZCIgPSAicmVzdWx0SWQiLCAicmFjZUlkIiA9ICJyYWNlSWQiLCAiY29uc3RydWN0b3JJZCIgPSAiY29uc3RydWN0b3JJZCIsICJwb3NpdGlvbiIgPSAicG9zaXRpb24iLCAicG9pbnRzIiA9ICJwb2ludHMiLCAibmFtZS54IiA9ICJuYW1lLngiLCAieWVhciIgPSAieWVhciIsICJyb3VuZCIgPSAicm91bmQiICwgInB1bnRvc19hY3VtdWxhZG9zIiA9ICJwdW50b3NfYWN1bXVsYWRvcyIpKSAlPiUgDQogIGZ1bGxfam9pbiguLCBhbG9fdnNfaGFtaWx0b24sIGMoImRyaXZlclJlZiI9ICJkcml2ZXJSZWYiLCAicmVzdWx0SWQiID0gInJlc3VsdElkIiwgInJhY2VJZCIgPSAicmFjZUlkIiwgImNvbnN0cnVjdG9ySWQiID0gImNvbnN0cnVjdG9ySWQiLCAicG9zaXRpb24iID0gInBvc2l0aW9uIiwgInBvaW50cyIgPSAicG9pbnRzIiwgIm5hbWUueCIgPSAibmFtZS54IiwgInllYXIiID0gInllYXIiLCAicm91bmQiID0gInJvdW5kIiwgInB1bnRvc19hY3VtdWxhZG9zIiA9ICJwdW50b3NfYWN1bXVsYWRvcyIpKSAlPiUgDQogIGZ1bGxfam9pbiguLCBhbG9fdnNfcGlxdWV0LCBjKCJkcml2ZXJSZWYiPSAiZHJpdmVyUmVmIiwgInJlc3VsdElkIiA9ICJyZXN1bHRJZCIsICJyYWNlSWQiID0gInJhY2VJZCIsICJjb25zdHJ1Y3RvcklkIiA9ICJjb25zdHJ1Y3RvcklkIiwgInBvc2l0aW9uIiA9ICJwb3NpdGlvbiIsICJwb2ludHMiID0gInBvaW50cyIsICJuYW1lLngiID0gIm5hbWUueCIsICJ5ZWFyIiA9ICJ5ZWFyIiwgInJvdW5kIiA9ICJyb3VuZCIsICJwdW50b3NfYWN1bXVsYWRvcyIgPSAicHVudG9zX2FjdW11bGFkb3MiKSkgJT4lIA0KICBmdWxsX2pvaW4oLiwgYWxvX3ZzX21hc3NhLCBjKCJkcml2ZXJSZWYiPSAiZHJpdmVyUmVmIiwgInJlc3VsdElkIiA9ICJyZXN1bHRJZCIsICJyYWNlSWQiID0gInJhY2VJZCIsICJjb25zdHJ1Y3RvcklkIiA9ICJjb25zdHJ1Y3RvcklkIiwgInBvc2l0aW9uIiA9ICJwb3NpdGlvbiIsICJwb2ludHMiID0gInBvaW50cyIsICJuYW1lLngiID0gIm5hbWUueCIsICJ5ZWFyIiA9ICJ5ZWFyIiwgInJvdW5kIiA9ICJyb3VuZCIsICJwdW50b3NfYWN1bXVsYWRvcyIgPSAicHVudG9zX2FjdW11bGFkb3MiKSkgICU+JSANCiAgZnVsbF9qb2luKC4sIGFsb192c19yYWlra29uZW4sIGMoImRyaXZlclJlZiI9ICJkcml2ZXJSZWYiLCAicmVzdWx0SWQiID0gInJlc3VsdElkIiwgInJhY2VJZCIgPSAicmFjZUlkIiwgImNvbnN0cnVjdG9ySWQiID0gImNvbnN0cnVjdG9ySWQiLCAicG9zaXRpb24iID0gInBvc2l0aW9uIiwgInBvaW50cyIgPSAicG9pbnRzIiwgIm5hbWUueCIgPSAibmFtZS54IiwgInllYXIiID0gInllYXIiLCAicm91bmQiID0gInJvdW5kIiwgInB1bnRvc19hY3VtdWxhZG9zIiA9ICJwdW50b3NfYWN1bXVsYWRvcyIpKSAlPiUgDQogIGZ1bGxfam9pbiguLCBhbG9fdnNfYnV0dG9uLCBjKCJkcml2ZXJSZWYiPSAiZHJpdmVyUmVmIiwgInJlc3VsdElkIiA9ICJyZXN1bHRJZCIsICJyYWNlSWQiID0gInJhY2VJZCIsICJjb25zdHJ1Y3RvcklkIiA9ICJjb25zdHJ1Y3RvcklkIiwgInBvc2l0aW9uIiA9ICJwb3NpdGlvbiIsICJwb2ludHMiID0gInBvaW50cyIsICJuYW1lLngiID0gIm5hbWUueCIsICJ5ZWFyIiA9ICJ5ZWFyIiwgInJvdW5kIiA9ICJyb3VuZCIsICJwdW50b3NfYWN1bXVsYWRvcyIgPSAicHVudG9zX2FjdW11bGFkb3MiKSkgJT4lIA0KICBmdWxsX2pvaW4oLiwgYWxvX3ZzX3ZhbmRvb3JuZSwgYygiZHJpdmVyUmVmIj0gImRyaXZlclJlZiIsICJyZXN1bHRJZCIgPSAicmVzdWx0SWQiLCAicmFjZUlkIiA9ICJyYWNlSWQiLCAiY29uc3RydWN0b3JJZCIgPSAiY29uc3RydWN0b3JJZCIsICJwb3NpdGlvbiIgPSAicG9zaXRpb24iLCAicG9pbnRzIiA9ICJwb2ludHMiLCAibmFtZS54IiA9ICJuYW1lLngiLCAieWVhciIgPSAieWVhciIsICJyb3VuZCIgPSAicm91bmQiLCAicHVudG9zX2FjdW11bGFkb3MiID0gInB1bnRvc19hY3VtdWxhZG9zIikpICU+JSANCiAgZnVsbF9qb2luKC4sIGFsb192c19vY29uLCBjKCJkcml2ZXJSZWYiPSAiZHJpdmVyUmVmIiwgInJlc3VsdElkIiA9ICJyZXN1bHRJZCIsICJyYWNlSWQiID0gInJhY2VJZCIsICJjb25zdHJ1Y3RvcklkIiA9ICJjb25zdHJ1Y3RvcklkIiwgInBvc2l0aW9uIiA9ICJwb3NpdGlvbiIsICJwb2ludHMiID0gInBvaW50cyIsICJuYW1lLngiID0gIm5hbWUueCIsICJ5ZWFyIiA9ICJ5ZWFyIiwgInJvdW5kIiA9ICJyb3VuZCIsICJwdW50b3NfYWN1bXVsYWRvcyIgPSAicHVudG9zX2FjdW11bGFkb3MiKSkNCg0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojZWwgbmFubyBjb250cmEgaGFtaWx0b24NCmZvdG9zX0FMT192c19IQU0gPC0gYygiLi9pbWFnZW5lcy9waWxvdG9zL2Fsb25zby5wbmciLCAiLi9pbWFnZW5lcy9waWxvdG9zL2hhbWlsdG9uLnBuZyIpDQpmb3Rvc19lc3BfaW5nIDwtIGMoIi4vaW1hZ2VuZXMvcGFpc2VzL2VzcGFueWEucG5nIiwgIi4vaW1hZ2VuZXMvcGFpc2VzL3VrLnBuZyIpDQpuX2NhcnJlcmFzX2Fsb19oYW0gPC0gbl9jYXJyZXJhc19ub20gJT4lIGZpbHRlcihkcml2ZXJSZWYgJWluJSBjKCJhbG9uc28iLCAiaGFtaWx0b24iKSkNCg0Kbl92aWN0b3JpYXNfYWxvX2hhbSA8LSB2aWN0b3JpYXNfY29uX25vbWJyZSAlPiUgZmlsdGVyKGRyaXZlclJlZiAlaW4lIGMoImFsb25zbyIsICJoYW1pbHRvbiIpKQ0KDQphbG9fdnNfaGFtIDwtIGZ1bGxfam9pbihuX2NhcnJlcmFzX2Fsb19oYW0sIG5fdmljdG9yaWFzX2Fsb19oYW0sIGMoImRyaXZlclJlZiI9ICJkcml2ZXJSZWYiKSkgJT4lIHNlbGVjdCggZHJpdmVyUmVmLCBudW1lcm9fY2FycmVyYXMsIG5fdmljdG9yaWFzKSAlPiUgYWRkX2NvbHVtbihmb3Rvc19lc3BfaW5nLCBmb3Rvc19BTE9fdnNfSEFNKSANCmBgYA0KDQoNCiMgMy4gVGhlIHBsYW4NCg0KIyMgMy4xIFVuIHBhc2VvIHBvciBsYSBoaXN0b3JpYSANCkVsIG5hY2ltaWVudG8gZGUgbGEgRsOzcm11bGEgMSBzZSByZW1vbnRhIGEgMTk1MCwgZG9uZGUgbGEgRklBLCBGZWRlcmFjacOzbiBJbnRlcm5hY2lvbmFsIGRlbCBBdXRvbcOzdmlsLCBkZWNpZGnDsyB1bmlyIHZhcmlvcyBncmFuZGVzIHByZW1pb3MgZGUgZGlmZXJlbnRlcyBwYcOtc2VzLCBwYXJhIGNyZWFyIGVsIGFtcGVvbmF0byB1bmRpYWwgZGUgcGlsb3Rvcy4gRWwgcHJpbWVyIGdyYW4gcHJlbWlvIHNlIGNlbGVicsOzIGVuIGVsIGNpcmN1aXRvIGRlIFNpbHZlcnN0b25lLCBlbCAxMyBkZSBtYXlvIGRlIDE5NTAuICBEZXNkZSBlbnRvbmNlcywgTGEgRsOzcm11bGEgMSBoYSBpZG8gZXZvbHVjaW9uYW5kbywgdGFudG8gYSBuaXZlbCBkZSBjb2NoZXMsIGNpcmN1aXRvcywgbyBsb2dvcywgcGFyYSBhY2FiYXIgc2llbmRvIGVsIGVzcGVjdMOhY3VsbyBxdWUgZXMgZW4gbGEgYWN0dWFsaWRhZC4NCg0KIyMjIENvY2hlcw0KRWwgYXV0b23Ds3ZpbCBwdWVkZSBzZXIgZWwgZWxlbWVudG8gcXVlIG1heW9yZXMgY2FtYmlvcyBoYSBleHBlcmltZXRuYWRvIGNvbiBlbCBwYXNvIGRlbCB0aWVtcG8uIEVuIGxvcyBhw7FvcyA1MCwgbGFzIGVzY3VkZXJpYXMgbcOhcyBkZXN0YWNhYmxlcyBlcmFuIGxvcyBwcm9waW9zIGZhYnJpY2FudGVzIGRlIHZlaMOtY3Vsb3MsIHBvciBlamVtcGxvIE1hc2VyYXRpIG8gQWxmYSBSb21lby4gTG9zIGNvY2hlcyBlbiBlc3RhIGTDqWNhZGEgc2UgY2FyYWN0ZXJpemFiYW4gcG9yIHRlbmVyIHVuIG1vdG9yIGZyb250YWwsIGEgZGlmZXJlbmNpYSBkZSBsbyBxdWUgcGFzYXLDrWEgZW4gYcOxb3MgcG9zdGVyaW9yZXMuICAgIA0KDQpBIHBhcnRpciBkZSBsYSBkw6ljYWRhIGRlIGxvcyA2MCwgc2UgY29tZW56YXJvbiBhIHV0aWxpemFyIHZlaMOtY3Vsb3MgY29uIG1vdG9yIGNlbnRyYWwsIHN1cG9uaWVuZG8gdW5hIGltcG9ydGFudGUgbWVqb3JhIGVuIGVsIGRlc2VtcGXDsW8gZGUgbG9zIGNvY2hlcy4gQWRlbcOhcywgc2UgZGlvIHBlc28gYSBvdHJvcyBhc3BlY3RvcywgY29tbyBsYSBjb21wb3NpY2nDs24gZGVsIGNoYXNpcywgc2llbmRvIGxhIGVzY3VkZXLDrWEgbG90dXMgcGlvbmVyYSBlbiBpbnRyb2R1Y2lyIGxvcyBjaGFzaXMgbW9ub2Nhc2NvIGRlIGFsdW1pbmlvLiAgIA0KDQpFbiBsb3MgNzAsIGxhIGFlcm9kaW7DoW1pY2EgcGFzw7MgYSB0ZW5lciB1biBwYXBlbCBmdW5kYW1lbnRhbCwgaW50cm9kdWNpZW5kb3NlIGVsIGVmZWN0byBzdWVsbywgcSBwZXJtaXTDrWEgcm9kYXIgYSBtYXlvciB2ZWxvY2lkYWQgZW4gbGFzIGN1cnZhcy4gRW50cmUgMTk4MCB5IDE5OTAgZGVzdGFjYW4gbGFzIGF5dWRhcyBlbGVjdHLDs25pY2FzLCBjb21vIHBvciBlamVtcGxvIGxhIHN1c3BlbnNpw7NuIGFjdGl2YSwgZWwgY2FtYmlvIGRlIG1hcmNoYXMgc2VtaS1hdXRvbcOhdGljbywgbyBlbCBjb250cm9sIGRlIHRyYWNjacOzbi4gICAgDQoNCkRlc2RlIGVudG9uY2VzLCBoYXN0YSBsYSBhY3R1YWxpZGFkLCBsb3MgY2FtbWJpb3MgZW4gbG9zIGNvY2hlcyBubyBoYW4gc2lkbyB0YW4gcmVsZXZhbnRlcywgcHJvZHVjaWVuZG9zZSB1biBlcXVpbGlicmlvIGVuIGxhcyBtZWpvcmFzIGRlIGxhcyBkaXN0aW50YXMgcGFydGVzIGRlbCB2ZWjDrWN1bG86IGFlcm9kaW7DoW1pY2EsIGNoYXNpcyB5IG1vdG9yLg0KYGBge3J9DQoNCmNvY2hlMTk1MCA8LSBpbWFnZV9yZWFkKCIuL2ltYWdlbmVzL2NvY2hlcy8xOTUwLmpwZyIpICU+JSBpbWFnZV9zY2FsZSguLCAiNTAwIikgJT4lICBpbWFnZV9hbm5vdGF0ZSguLCAiMTk1MCIsIHNpemUgPSA0MCwgZ3Jhdml0eSA9ICJzb3V0aHdlc3QiLCBjb2xvciA9ICJ3aGl0ZSIpDQpjb2NoZTE5NjAgPC0gaW1hZ2VfcmVhZCgiLi9pbWFnZW5lcy9jb2NoZXMvMTk2MC5qcGciKSAlPiUgaW1hZ2Vfc2NhbGUoLiwgIjUwMCIpJT4lICBpbWFnZV9hbm5vdGF0ZSguLCAiMTk2MCIsIHNpemUgPSA0MCwgZ3Jhdml0eSA9ICJzb3V0aHdlc3QiLCBjb2xvciA9ICJ3aGl0ZSIpDQpjb2NoZTE5NzAgPC0gaW1hZ2VfcmVhZCgiLi9pbWFnZW5lcy9jb2NoZXMvMTk3MC5qcGciKSAlPiUgaW1hZ2Vfc2NhbGUoLiwgIjUwMCIpJT4lICBpbWFnZV9hbm5vdGF0ZSguLCAiMTk3MCIsIHNpemUgPSA0MCwgZ3Jhdml0eSA9ICJzb3V0aHdlc3QiLCBjb2xvciA9ICJ3aGl0ZSIpDQpjb2NoZTE5ODAgPC0gaW1hZ2VfcmVhZCgiLi9pbWFnZW5lcy9jb2NoZXMvMTk4MC5qcGciKSAlPiUgaW1hZ2Vfc2NhbGUoLiwgIjUwMCIpJT4lICBpbWFnZV9hbm5vdGF0ZSguLCAiMTk4MCIsIHNpemUgPSA0MCwgZ3Jhdml0eSA9ICJzb3V0aHdlc3QiLCBjb2xvciA9ICJ3aGl0ZSIpDQpjb2NoZTE5OTAgPC0gaW1hZ2VfcmVhZCgiLi9pbWFnZW5lcy9jb2NoZXMvMTk5MC5qcGciKSAlPiUgaW1hZ2Vfc2NhbGUoLiwgIjUwMCIpJT4lICBpbWFnZV9hbm5vdGF0ZSguLCAiMTk5MCIsIHNpemUgPSA0MCwgZ3Jhdml0eSA9ICJzb3V0aHdlc3QiLCBjb2xvciA9ICJ3aGl0ZSIpDQpjb2NoZTIwMDUgPC0gaW1hZ2VfcmVhZCgiLi9pbWFnZW5lcy9jb2NoZXMvMjAwNS5qcGciKSAlPiUgaW1hZ2Vfc2NhbGUoLiwgIjUwMCIpJT4lICBpbWFnZV9hbm5vdGF0ZSguLCAiMjAwNSIsIHNpemUgPSA0MCwgZ3Jhdml0eSA9ICJzb3V0aHdlc3QiLCBjb2xvciA9ICJ3aGl0ZSIpDQpjb2NoZTIwMjAgPC0gaW1hZ2VfcmVhZCgiLi9pbWFnZW5lcy9jb2NoZXMvMjAyMC5qcGciKSAlPiUgaW1hZ2Vfc2NhbGUoLiwgIjUwMCIpJT4lICBpbWFnZV9hbm5vdGF0ZSguLCAiMjAyMCIsIHNpemUgPSA0MCwgZ3Jhdml0eSA9ICJzb3V0aHdlc3QiLCBjb2xvciA9ICJ3aGl0ZSIpDQpjb2NoZXMgPC0gYyhjb2NoZTE5NTAsIGNvY2hlMTk2MCwgY29jaGUxOTcwLCBjb2NoZTE5ODAsIGNvY2hlMTk5MCwgY29jaGUyMDA1LCBjb2NoZTIwMjApDQoNCmltYWdlX2FuaW1hdGUoaW1hZ2Vfc2NhbGUoY29jaGVzKSwgZnBzID0gMC41KQ0KYGBgDQoNCiMjIyBMb2dvcyAgey50YWJzZXR9DQoNCiMjIyMgTG9nbyBkZSAxOTg1IGEgMTk4Ng0KDQpBdW5xdWUgbm8gdGFuIGVzcGVjdGFjdWxhciwgdGFtYmnDqW4gc2UgaGEgcHJvZHVjaWRvIHVhIGV2b2x1Y2nDs24gZGUgbGEgZXN0w6l0aWNhIGRlbCBsb2dvLCBwYXNhbmRvIGRlIHVuYSBpbWFnZW4gbcOhcyBjYXJnYWRhLCBlbiBsYSBxdWUgYXBhcmVjZSBoYXN0YSBlbCBzw61tYm9sbyBkZSBsYSBGSUEsIGFsIGxvZ28gYWN0dWFsLCBjb21wdWVzdG8gcG9yIGxhIEYgeSBlbCAxLg0KDQo8Y2VudGVyPg0KIVtMb2dvIGRlIDE5NTAgYSAxOTg2XSguL2ltYWdlbmVzL2xvZ29zLzE5ODUtMTk4Ni5wbmcpe3dpZHRoPTQwMCBoZWlnaHQ9NzB9DQo8L2NlbnRlcj4NCg0KDQojIyMjIExvZ28gZGUgMTk4NyBhIDE5OTMNCjxjZW50ZXI+DQohW0xvZ28gZGUgMTk4NyBhIDE5OTNdKC4vaW1hZ2VuZXMvbG9nb3MvMTk4Ny0xOTkzLmpwZyl7d2lkdGg9MjUwIGhlaWdodD0zMDB9DQo8L2NlbnRlcj4NCg0KDQojIyMjIExvZ28gZGUgMTk5NCBhIDIwMTcNCjxjZW50ZXI+DQohW0xvZ28gZGUgMTk5NCBhIDIwMTddKC4vaW1hZ2VuZXMvbG9nb3MvMTk5NC0yMDE3LnBuZyl7d2lkdGg9NDUwIGhlaWdodD0zMDB9DQo8L2NlbnRlcj4NCg0KDQojIyMjIExvZ28gQWN0dWFsDQo8Y2VudGVyPg0KIVtMT0dPIGRlc2RlIDIwMTggaGFzdGEgbGEgYWN0dWFsaWRhZF0oLi9pbWFnZW5lcy9sb2dvcy8yMDE4LS5wbmcpe3dpZHRoPTQwMCBoZWlnaHQ9MzAwfQ0KPC9jZW50ZXI+ICANCg0KDQojIyMgQ2Fww610dWxvIG9zY3VybyBkZWwgZGVwb3J0ZQ0KDQpIYXkgcXVlIHNlciBjb25zY2llbnRlcyBxdWUsIGRlIGlndWFsIG1hbmVyYSBxdWUgbGEgRm9ybXVsYSAxIGVzIGVzcGVjdGFjdWxhciwgc3VzIHBpbG90b3Mgc2UgZXhwb25lbiBhIHVuIGdyYW4gcmllc2dvLCBkZWJpZG8gYSBsYXMgdmVsb2NpZGFkZXMgcXVlIGFsY2FuemFuLiBQcnVlYmEgZGUgZWxsbyBlcywgZWwgZ3LDoWZpY28gbW9zdHJhZG8gYSBjb250aW51YWNpw7NuLCBlbiBlbCBjdWFsIHNlIHJlZmxlamEgdG9kYXMgbGFzIG11ZXJ0ZXMgZGUgcGlsb3RvcyBwcm9kdWNpZGFzIGVuIGxhIEYxLiBFbCAgdG90YWwgZXMgZGUgNDIsIHNpZW5kbyBsYSBwZW9yIGRlY2FkYSBsb3MgYcOxb3MgNTAsIHByb2R1Y2llbmRvc2UgMTUgZmFsbGVjaW1pZW50b3MuICAgICAgIA0KDQpTaW4gZW1iYXJnbywgbGEgdGVuZGVuY2lhIGhhIHNpZG8gY2xhcmFtZW50ZSBuZWdhdGl2YSwgZGViaWRvIGEgbGFzIGRpZmVyZW50ZXMgbWVkaWRhcyBkZSBzZWd1cmlkYWQgcXVlIHNlIGhhbiBpZG8gaW5jb3Jwb3JhbmRvLiBMYSDDumx0aW1hIGludHJvZHVjY2nDs24gaGEgc2lkbyBlbCBoYWxvLCBjZW50cmFkbyBlbiBldml0YXIgZ29scGVzIG8gYXBsYXN0YW1pZW50b3MgZGUgbGEgY2FiZXphIGRlbCBwaWxvdG8uIE90cmFzIG1lam9yYXMgZGVzdGFjYWRhcyBoYW4gc2lkbywgbGFzIHByb3RlY2lvbmVzIHkgZ3JhdmEgZW4gbG9zIGNpcmN1aXRvcywgbG9zIG1vbm9zIGlnbsOtZnVnb3MgbyBsYSByZWdsYW1lbnRhY2nDs24gZW4gZWwgZGlzZcOxbyBkZWwgY2FzY28uDQoNCmBgYHtyLCBldmFsID0gVFJVRSwgZWNobyA9IFRSVUV9DQpnZ19tdWVydGVzIDwtIGdncGxvdChtdWVydGVzZjFfZmluYWwsIGFlcyh4ID0gZmVjaGFfbXVlcnRlLCB5ID0gbXVlcnRlc3hhbnlvICkpICsgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gIndoaXRlIiwgY29sb3VyID0gIndoaXRlIikgKyBnZW9tX3Ntb290aChjb2xvdXIgPSAiY3lhbiIsIHNlID0gRkFMU0UpICsgbGFicyh4ID0gIkHDsW8iICwgeSA9ICJOw7ptZXJvIGRlIG11ZXJ0ZXMiKSAgKyB0aGVtZShheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gIndoaXRlIiksDQogICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAid2hpdGUiKSwNCiAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmF5MTMiKSwNCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmF5MTMiKSwNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJ3aGl0ZSIpLA0KICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAid2hpdGUiKSwNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJ3aGl0ZSIpLA0KICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiLA0KICAgICAgICBjb2xvdXIgPSAid2hpdGUiKSwgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTEzIikpICtsYWJzKGNvbG91ciA9ICJ3aGl0ZSIpICsgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTM4IiwNCiAgICBsaW5ldHlwZSA9ICJkb3R0ZWQiKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSBOQSksDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjUsDQogICAgICAgIGhqdXN0ID0gMC41KSkgK2xhYnModGl0bGUgPSAiQWNjaWRlbnRlcyBtb3J0YWxlcyBwb3IgYcOxbyIpICsgZ2VvbV90ZXh0KGRhdGEgPSBkYXRhLmZyYW1lKHggPSAyMDA0LjEwNTIyNjQyODc1LCB5ID0gMC4yMzc0NTA1MTY5NDIyNDEsIA0KICAgIGxhYmVsID0gIlRlbmRlbmNpYSBuZWdhdGl2YSIpLCBtYXBwaW5nID0gYWVzKHggPSB4LCB5ID0geSwgDQogICAgbGFiZWwgPSBsYWJlbCksIGNvbG91ciA9ICJjeWFuIiwgaW5oZXJpdC5hZXMgPSBGQUxTRSwgc2l6ZSA9IDMpDQoNCmdncGxvdGx5KGdnX211ZXJ0ZXMpDQoNCg0KYGBgDQoNCg0KIyMgMy4yIExvIG3DoXMgZGVzdGFjYWRvIA0KDQoNCiMjIyBBdWRlbmNpYXMNCmBgYHtyLCBldmFsID0gVFJVRSwgZWNobyA9IFRSVUV9DQphdWRpZW5jaWFzIDwtIHJpbzo6aW1wb3J0KGZpbGUgPSAiLi9kYXRvcy9hdWRpZW5jaWFzRjEuY3N2IikNCg0KDQpnZ19hdWRpZW5jaWFzIDwtIGdncGxvdChhdWRpZW5jaWFzLCBhZXMoeD15ZWFyLCB5PSBudW1lcm9fZXNwZWN0YWRvcmVzKSkgKw0KICBnZW9tX2FyZWEoKSArDQogIGdlb21fcG9pbnQoIHNpemU9MS41LCBjb2xvcj0iY3lhbiIsIGZpbGw9YWxwaGEoImN5YW4iLCA4KSwgc2hhcGU9MjEsIHN0cm9rZT0yKSArICANCiAgZ2VvbV9saW5lKGNvbG9yPSIjNjliM2EyIiwgc2l6ZT0xKSArDQogIHNjYWxlX3hfY29udGludW91cygNCiAgICBicmVha3MgPSBzZXEoMjAwNCwgMjAyMCwgMSksDQogICAgbGltaXRzID0gYygyMDAzLCAyMDIxKSkgKyBsYWJzKHggPSAiQcOxbyIsIHkgPSAiTnVtZXJvIGRlIGVzcGVjdGFkb3JlcyIgKSAgKyB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTEzIiksDQogICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTEzIikpICsgdGhlbWUoYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJ3aGl0ZSIpLA0KICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyYXkyMCIpLA0KICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyYXkyMCIpLA0KICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAid2hpdGUiKSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAid2hpdGUiKSwNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJ3aGl0ZSIsDQogICAgICAgIGhqdXN0ID0gMC41KSkgK2xhYnModGl0bGUgPSAiRXZvbHVjacOzbiBkZSBsYSBhdWRpZW5jaWEiLA0KICAgIGNvbG91ciA9ICJ3aGl0ZSIpICsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDQpKQ0KDQoNCmdncGxvdGx5KGdnX2F1ZGllbmNpYXMpDQoNCmBgYA0KDQoNCiMjIyBQcmVzdXB1ZXN0b3MNCg0KYGBge3IsIGV2YWwgPSBUUlVFLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC5leHRyYT0nYW5nbGU9OTAnLCBlY2hvID0gVFJVRX0NCg0KcHJlc3VwdWVzdG9zIDwtIHJlYWRfZXhjZWwoImRhdG9zL3ByZXN1cHVlc3Rvcy54bHN4IikNCg0KZ2dfcHJlc3VwIDwtIGdncGxvdChwcmVzdXB1ZXN0b3MsIGFlcyh5ZWFyLCBQcmVzdXB1ZXN0bywgY29sb3IgPSBFc2N1ZGVyaWEpKSArIA0KICBnZW9tX3BvaW50KCkgKyBnZW9tX2xpbmUoKSArIA0KICBsYWJzKHggPSAiQcOxbyIsIHkgPSAiUHJlc3VwdWVzdG8gZW4g4oKsIiApICsNCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoDQogICAgYnJlYWtzID0gc2VxKDIwMTUsIDIwMjMsIDEpLA0KICAgIGxpbWl0cyA9IGMoMjAxNCwgMjAyNCkpICsgDQogIHNjYWxlX3lfY29udGludW91cyggYnJlYWtzID0gc2VxKDAsIDcwMDAwMDAwMCwgMTAwMDAwMDAwKSwNCiAgICBsaW1pdHMgPSBjKDAsIDYwMDAwMDAwMCkpICArIHRoZW1lKGF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gIndoaXRlIiksDQogICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAid2hpdGUiLA0KICAgICAgICBsaW5ldHlwZSA9ICJibGFuayIpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJ3aGl0ZSIsDQogICAgICAgIGxpbmV0eXBlID0gImJsYW5rIiksIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LA0KICAgICAgICBmYWNlID0gImJvbGQiLCBjb2xvdXIgPSAiY3lhbiIsIHZqdXN0ID0gMC43NSksDQogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJ3aGl0ZSIpLA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LA0KICAgICAgICBmYWNlID0gImJvbGQiLCBjb2xvdXIgPSAiY3lhbiIsIGhqdXN0ID0gMC41LA0KICAgICAgICB2anVzdCA9IDAuNzUpLCBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLA0KICAgICAgICBjb2xvdXIgPSAiY3lhbiIpLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzLA0KICAgICAgICBmYWNlID0gImJvbGQiLCBjb2xvdXIgPSAiY3lhbiIpLA0KICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiLA0KICAgICAgICBjb2xvdXIgPSAid2hpdGUiKSwgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTEzIiksDQogICAgbGVnZW5kLmtleSA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXkxMyIpLA0KICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTEzIikpICtsYWJzKHRpdGxlID0gIlBSRVNVUFVFU1RPIERFIENBREEgRVFVSVBPIFBPUiBURU1QT1JBREEiKSArIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gTkEpLA0KICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gTkEpLA0KICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSwNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksDQogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpLA0KICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLA0KICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiLA0KICAgICAgICBjb2xvdXIgPSBOQSksIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXkxMyIsDQogICAgICAgIGNvbG91ciA9IE5BKSkgKyB0aGVtZShsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTEzIiksDQogICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiKSkgKyB0aGVtZShheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyYXkyMCIsDQogICAgbGluZXR5cGUgPSAic29saWQiKSwgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTE1IiwNCiAgICBsaW5ldHlwZSA9ICJzb2xpZCIpKQ0KIA0KZ2dwbG90bHkoZ2dfcHJlc3VwKSAjcGFyYSBxdWUgc2VhIGludGVyYWN0aXZvDQpgYGANCg0KDQojIyMgTmFjaW9uYWxpZGFkZXMgey50YWJzZXR9DQoNCiMjIyMgTWFwYQ0KYGBge3J9DQoNCmdncGxvdGx5KGdnX3BpbG90b3NfcG9yX3BhaXNlcykNCg0KYGBgDQoNCiMjIyMgVGFibGEgDQoNCmBgYHtyLCBldmFsID0gVFJVRSwgZWNobyA9IFRSVUV9DQoNCnNldF9mbGV4dGFibGVfZGVmYXVsdHMoDQogIGZvbnQuc2l6ZSA9IDE1LA0KICBmb250LmNvbG9yID0gIndoaXRlIiwNCiAgdGFibGUubGF5b3V0ID0gImZpeGVkIiwgDQogIGJhY2tncm91bmQuY29sb3IgPSAiZ3JheTEzIikNCg0KZmxleF9waWxvdG8gPC0gZmxleHRhYmxlKG5hY2lvbmFsaWRhZCkNCg0Kc21hbGxfYm9yZGVyID0gZnBfYm9yZGVyKGNvbG9yPSJncmF5NTAiLCB3aWR0aCA9IDIpDQoNCmZsZXhfcGlsb3RvMSA8LSBib3JkZXJfb3V0ZXIoZmxleF9waWxvdG8sIHBhcnQ9ImFsbCIsIGJvcmRlciA9IHNtYWxsX2JvcmRlciApDQoNCg0KdGhlbWVfdmFkZXIoZmxleF9waWxvdG8xKQ0KYGBgDQoNCg0KIyMjIFBpbG90b3MgY29uIG3DoXMgdmljdG9yaWFzDQpgYGB7ciwgZXZhbCA9IFRSVUUsIGVjaG8gPSBUUlVFfQ0KDQpnZ3Bsb3QodmljdG9yaWFzMiwgYWVzKHggPSByZW9yZGVyKGRyaXZlclJlZixzdW1hX3ZpYyksIHN1bWFfdmljKSkgKyANCiAgZ2VvbV9saW5lKHNpemU9NSwgY29sb3VyID0gImN5YW4iKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLA0KICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUsDQogICAgICAgIGNvbG91ciA9ICJ3aGl0ZSIsIGhqdXN0ID0gMCksIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTIwIiwNCiAgICAgICAgbGluZXR5cGUgPSAic29saWQiKSwgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJibGFuayIpLA0KICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUobGluZXR5cGUgPSAiYmxhbmsiKSwNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJjeWFuIiksDQogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJjeWFuIiksDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3VyID0gIndoaXRlIiksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoY29sb3VyID0gIndoaXRlIiksDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTcsDQogICAgICAgIGNvbG91ciA9ICJ3aGl0ZSIsIGhqdXN0ID0gMC41KSwgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXkxMyIsDQogICAgICAgIGNvbG91ciA9ICJncmF5MTMiLCBsaW5ldHlwZSA9ICJzb2xpZCIpLA0KICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXkxMyIsDQogICAgICAgIGNvbG91ciA9ICJncmF5MTMiLCBsaW5ldHlwZSA9ICJzb2xpZCIpKSArbGFicyh0aXRsZSA9ICdQaWxvdG9zIGNvbiBtw6FzIHZpY3RvcmlhcycgLHggPSAiUGlsb3RvcyIsDQogICAgeSA9ICJOwrogdmljdG9yaWFzIikgKyB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJncmF5NTAiKSwNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsDQogICAgICAgIGNvbG91ciA9ICJjeWFuIikpICtsYWJzKHRpdGxlID0gIlBJTE9UT1MgQ09OIE3DgVMgVklDVE9SSUFTIiwNCiAgICBzdWJ0aXRsZSA9ICkgIysgdHJhbnNpdGlvbl9yZXZlYWwoZGF0ZSkNCg0KDQpgYGANCg0KDQojIyMgUmVtYW5kbyBhIGNvbnRyYWNvcnJpZW50ZQ0KYGBge3IsIGV2YWwgPSBUUlVFLCBlY2hvID0gVFJVRX0NCnRydWxsaSA8LSByZWFkUE5HKCIuL2ltYWdlbmVzL3BpbG90b3MvdHJ1bGxpLnBuZyIpDQprb3ZhbGFpbmVuIDwtIHJlYWRQTkcoIi4vaW1hZ2VuZXMvcGlsb3Rvcy9rb3ZhbGFpbmVuLnBuZyIpDQp2ZXR0ZWwgPC0gcmVhZFBORygiLi9pbWFnZW5lcy9waWxvdG9zL3ZldHRlbC5wbmciKQ0KcmFpa2tvbmVuIDwtIHJlYWRQTkcoIi4vaW1hZ2VuZXMvcGlsb3Rvcy9yYWlra29uZW4ucG5nIikNCnNjaHVtYWNoZXIgPC0gcmVhZFBORygiLi9pbWFnZW5lcy9waWxvdG9zL3NjaHVtYWNoZXIucG5nIikNCmhhbWlsdG9uIDwtIHJlYWRQTkcoIi4vaW1hZ2VuZXMvcGlsb3Rvcy9oYW1pbHRvbi5wbmciKQ0KbW9udG95YSA8LSByZWFkUE5HKCIuL2ltYWdlbmVzL3BpbG90b3MvbW9udG95YS5wbmciKQ0KYWxvbnNvIDwtIHJlYWRQTkcoIi4vaW1hZ2VuZXMvcGlsb3Rvcy9hbG9uc28ucG5nIikNCg0KdHJ1bGxpX2dyb2IgPC0gcmFzdGVyR3JvYih0cnVsbGksIGludGVycG9sYXRlPVRSVUUpDQprb3ZhbGFpbmVuX2dyb2IgPC0gcmFzdGVyR3JvYihrb3ZhbGFpbmVuLCBpbnRlcnBvbGF0ZT1UUlVFKQ0KdmV0dGVsX2dyb2IgPC0gcmFzdGVyR3JvYih2ZXR0ZWwsIGludGVycG9sYXRlPVRSVUUpDQpyYWlra29uZW5fZ3JvYiA8LSByYXN0ZXJHcm9iKHJhaWtrb25lbiwgaW50ZXJwb2xhdGU9VFJVRSkNCnNjaHVtYWNoZXJfZ3JvYiA8LSByYXN0ZXJHcm9iKHNjaHVtYWNoZXIsIGludGVycG9sYXRlPVRSVUUpDQpoYW1pbHRvbl9ncm9iIDwtIHJhc3Rlckdyb2IoaGFtaWx0b24sIGludGVycG9sYXRlPVRSVUUpDQptb250b3lhX2dyb2IgPC0gcmFzdGVyR3JvYihtb250b3lhLCBpbnRlcnBvbGF0ZT1UUlVFKQ0KYWxvbnNvX2dyb2IgPC0gcmFzdGVyR3JvYihhbG9uc28sIGludGVycG9sYXRlPVRSVUUpDQoNCg0KZ2dyZW1vbnRhZG9zIDwtIGdncGxvdChwdWVzdG9zX3JlbW9udF9waWxvdG9fcmVjaWVudCwgYWVzKHggPSByZW9yZGVyKGRyaXZlclJlZiwgcmVtb250YWRvcyksIHJlbW9udGFkb3MpKSAgKyBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKyBjb29yZF9mbGlwKCkgKyBsYWJzKHggPSAiUGlsb3RvcyIsIHkgPSAiTsK6IGRlIHB1ZXN0b3MgcmVtb250YWRvcyIgKSArIGFubm90YXRpb25fY3VzdG9tKGFsb25zb19ncm9iLCB4bWluPSAtMTUsIHhtYXg9MTcsIHltaW49IDE4LCB5bWF4PTIwKSArDQogIGFubm90YXRpb25fY3VzdG9tKGtvdmFsYWluZW5fZ3JvYiwgeG1pbj0gLTIwLCB4bWF4PTI0LCB5bWluPSAxOC42NSwgeW1heD0yMCkgKw0KICBhbm5vdGF0aW9uX2N1c3RvbShtb250b3lhX2dyb2IsIHhtaW49IC0yNi43LCB4bWF4PTMzLCB5bWluPSAxOCwgeW1heD0yMS4yKSArDQogIGFubm90YXRpb25fY3VzdG9tKHRydWxsaV9ncm9iLCB4bWluPSAtMzIsIHhtYXg9NDAuLCB5bWluPSAxOC4zLCB5bWF4PTE5LjU1KSArDQogIGFubm90YXRpb25fY3VzdG9tKGhhbWlsdG9uX2dyb2IsIHhtaW49IC0zMiwgeG1heD00Mi4yLCB5bWluPSAxOSwgeW1heD0yMS44KSArDQogIGFubm90YXRpb25fY3VzdG9tKHNjaHVtYWNoZXJfZ3JvYiwgeG1pbj0gLTMyLCB4bWF4PTQ0LjEsIHltaW49IDE5LjIsIHltYXg9MjAuNSkgKw0KICBhbm5vdGF0aW9uX2N1c3RvbShyYWlra29uZW5fZ3JvYiwgeG1pbj0gLTMyLCB4bWF4PTQ2LjEsIHltaW49IDE5LCB5bWF4PTIxKSArDQogIGFubm90YXRpb25fY3VzdG9tKHZldHRlbF9ncm9iLCB4bWluPSAtMzIsIHhtYXg9NDguMSwgeW1pbj0gMTksIHltYXg9MjEuMikgKw0KICAgIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAid2hpdGUiKSwNCiAgICBheGlzLnRpY2tzID0gZWxlbWVudF9saW5lKGNvbG91ciA9IE5BKSwNCiAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJjeWFuIiwNCiAgICAgICAgbGluZXR5cGUgPSAiYmxhbmsiKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTIwIiksDQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLA0KICAgICAgICBjb2xvdXIgPSAiZ3JheTUwIiksIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEsDQogICAgICAgIGNvbG91ciA9ICJjeWFuIiksIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJjeWFuIiksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoY29sb3VyID0gImN5YW4iKSwNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSwNCiAgICAgICAgZmFjZSA9ICJib2xkIiwgY29sb3VyID0gImN5YW4iLCBoanVzdCA9IDAuNDUsDQogICAgICAgIHZqdXN0ID0gMC43NSksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiLA0KICAgICAgICBsaW5ldHlwZSA9ICJzb2xpZCIpLCBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiLA0KICAgICAgICBjb2xvdXIgPSAiY3lhbiIsIGxpbmV0eXBlID0gInNvbGlkIikpICtsYWJzKHRpdGxlID0gIk1BWU9SRVMgUkVNT05UQURBUyBFTiBMQSBISVNUT1JJQSIpDQogIA0KDQpnZ3JlbW9udGFkb3MNCg0KYGBgDQoNCiMjIyBNdW5kaWFsZXMgcG9yIGVzY3VkZXJpYXMgeSBwaWxvdG9zIHsudGFic2V0fQ0KDQojIyMjIEVuIHZhbG9yZXMgcmVsYXRpdm9zDQpgYGB7ciwgZXZhbCA9IFRSVUUsIGVjaG8gPSBUUlVFLCBpbmNsdWRlID0gRkFMU0V9DQojZGF0b3MgZGUgZXNjdWRlcmlhcyBwYSBxdWllbiBxdWllcmEgaGFjZXIgYWxnbw0KZXNjdWRlcmlhcyA8LSByaW86OmltcG9ydChmaWxlID0gIi4vZGF0b3MvY29uc3RydWN0b3JzLmNzdiIpDQplc2N1ZGVyaWFzMiA8LSByaW86OmltcG9ydChmaWxlID0gIi4vZGF0b3MvY29uc3RydWN0b3Jfc3RhbmRpbmdzLmNzdiIpDQpyZXN1bHRfZXNjdWRlcmlhcyA8LSByaW86OmltcG9ydChmaWxlID0gIi4vZGF0b3MvY29uc3RydWN0b3JfcmVzdWx0cy5jc3YiKQ0KDQpwaWxvdG9zIDwtIHJpbzo6aW1wb3J0KGZpbGUgPSAiLi9kYXRvcy9kcml2ZXJzLmNzdiIpDQpyZXN1bHRhZG9zIDwtIHJpbzo6aW1wb3J0KGZpbGUgPSAiLi9kYXRvcy9yZXN1bHRzLmNzdiIpDQpjYXJyZXJhcyA8LSByaW86OmltcG9ydChmaWxlID0gIi4vZGF0b3MvcmFjZXMuY3N2IikNCiNlc2N1ZGVyaWFzZXNwIDwtIGVzY3VkZXJpYXMgJT4lIGZpbHRlcihuYXRpb25hbGl0eSA9PSAiU3BhbmlzaCIpICNlc2N1ZGVyaWFzIGVzcGHDsW9sYXMNCg0KY2FtcGVvbmVzX2VzYyA8LSBmdWxsX2pvaW4ocGlsb3RvcywgcmVzdWx0YWRvcywgYygiZHJpdmVySWQiID0gImRyaXZlcklkIikpICU+JSBmdWxsX2pvaW4oLiwgY2FycmVyYXMsIGMoInJhY2VJZCIgPSAicmFjZUlkIikpICU+JSBzZWxlY3QoZHJpdmVySWQsIGRyaXZlclJlZiwgbmF0aW9uYWxpdHksIGNvbnN0cnVjdG9ySWQsIHBvaW50cywgeWVhciwgcm91bmQpICU+JSBmdWxsX2pvaW4oLiwgZXNjdWRlcmlhcywgYygiY29uc3RydWN0b3JJZCIgPSAiY29uc3RydWN0b3JJZCIpKSAlPiUgc2VsZWN0KGRyaXZlcklkLCBkcml2ZXJSZWYsIG5hdGlvbmFsaXR5LngsIGNvbnN0cnVjdG9ySWQsIHBvaW50cywgeWVhciwgbmFtZSwgcm91bmQpICU+JSAgZ3JvdXBfYnkoeWVhciwgZHJpdmVyUmVmKSAlPiUgIG11dGF0ZShwdW50b3NfdG90YWxlcyA9IGN1bXN1bShwb2ludHMpKSAlPiUgdW5ncm91cCgpICU+JSBncm91cF9ieSh5ZWFyKSAlPiUgc2xpY2VfbWF4KHB1bnRvc190b3RhbGVzLCBuPTEpICU+JSBzZWxlY3QobmFtZSwgZHJpdmVyUmVmKSAlPiUgZ3JvdXBfYnkobmFtZSwgZHJpdmVyUmVmKSAlPiUgbXV0YXRlKHRvdGFsX2NhbXAgPSBzdW0oIE5OID0gbigpKSkgJT4lIGFycmFuZ2UobmFtZSkgDQoNCg0KDQoNCmxpYnJhcnkodHJlZW1hcCkNCmxpYnJhcnkoZDN0cmVlUikNCg0KDQojIGJhc2ljIHRyZWVtYXANCmdnX2VzY19jYW1wZW9uZXMgPC0gdHJlZW1hcChjYW1wZW9uZXNfZXNjLA0KICAgICAgICAgICAgaW5kZXg9YygibmFtZSIsImRyaXZlclJlZiIpLA0KICAgICAgICAgICAgdlNpemU9InRvdGFsX2NhbXAiLA0KICAgICAgICAgICAgdHlwZT0iaW5kZXgiLA0KICAgICAgICAgICAgdkNvbG9yID0gIm5hbWUiLA0KICAgICAgICAgICAgZm9udHNpemUubGFiZWxzPWMoMTUsMjApLA0KICAgICAgICAgICAgYmcubGFiZWxzPWMoInRyYW5zcGFyZW50IiksDQogICAgICAgICAgICBwYWxldHRlID0gIlNldDIiLA0KICAgICAgICAgICAgYWxpZ24ubGFiZWxzPWxpc3QoDQogICAgICAgICAgICAgIGMoImNlbnRlciIsICJjZW50ZXIiKSwgDQogICAgICAgICAgICAgIGMoImNlbnRlciIsICJib3R0b20iKSksDQogICAgICAgICAgICB0aXRsZSA9ICJFc2N1ZGVyw61hcyBjb24gbcOhcyBjYW1wZW9uZXMiLA0KICAgICAgICAgICAgdGl0bGUubGVnZW5kID0gIkVzY3VkZXLDrWFzIikgICANCg0KYGBgDQoNCg0KYGBge3IsIGV2YWwgPSBUUlVFLCBlY2hvID0gVFJVRX0NCiNkYXRvcyBkZSBlc2N1ZGVyaWFzIHBhIHF1aWVuIHF1aWVyYSBoYWNlciBhbGdvDQojZXNjdWRlcmlhcyA8LSByaW86OmltcG9ydChmaWxlID0gIi4vZGF0b3MvY29uc3RydWN0b3JzLmNzdiIpDQojZXNjdWRlcmlhczIgPC0gcmlvOjppbXBvcnQoZmlsZSA9ICIuL2RhdG9zL2NvbnN0cnVjdG9yX3N0YW5kaW5ncy5jc3YiKQ0KI3Jlc3VsdF9lc2N1ZGVyaWFzIDwtIHJpbzo6aW1wb3J0KGZpbGUgPSAiLi9kYXRvcy9jb25zdHJ1Y3Rvcl9yZXN1bHRzLmNzdiIpDQoNCiNwaWxvdG9zIDwtIHJpbzo6aW1wb3J0KGZpbGUgPSAiLi9kYXRvcy9kcml2ZXJzLmNzdiIpDQojcmVzdWx0YWRvcyA8LSByaW86OmltcG9ydChmaWxlID0gIi4vZGF0b3MvcmVzdWx0cy5jc3YiKQ0KI2NhcnJlcmFzIDwtIHJpbzo6aW1wb3J0KGZpbGUgPSAiLi9kYXRvcy9yYWNlcy5jc3YiKQ0KI2VzY3VkZXJpYXNlc3AgPC0gZXNjdWRlcmlhcyAlPiUgZmlsdGVyKG5hdGlvbmFsaXR5ID09ICJTcGFuaXNoIikgI2VzY3VkZXJpYXMgZXNwYcOxb2xhcw0KDQojY2FtcGVvbmVzX2VzYyA8LSBmdWxsX2pvaW4ocGlsb3RvcywgcmVzdWx0YWRvcywgYygiZHJpdmVySWQiID0gImRyaXZlcklkIikpICU+JSBmdWxsX2pvaW4oLiwgY2FycmVyYXMsIGMoInJhY2VJZCIgPSAicmFjZUlkIikpICU+JSBzZWxlY3QoZHJpdmVySWQsIGRyaXZlclJlZiwgbmF0aW9uYWxpdHksIGNvbnN0cnVjdG9ySWQsIHBvaW50cywgeWVhciwgcm91bmQpICU+JSBmdWxsX2pvaW4oLiwgZXNjdWRlcmlhcywgYygiY29uc3RydWN0b3JJZCIgPSAiY29uc3RydWN0b3JJZCIpKSAlPiUgc2VsZWN0KGRyaXZlcklkLCBkcml2ZXJSZWYsIG5hdGlvbmFsaXR5LngsIGNvbnN0cnVjdG9ySWQsIHBvaW50cywgeWVhciwgbmFtZSwgcm91bmQpICU+JSAgZ3JvdXBfYnkoeWVhciwgZHJpdmVyUmVmKSAlPiUgIG11dGF0ZShwdW50b3NfdG90YWxlcyA9IGN1bXN1bShwb2ludHMpKSAlPiUgdW5ncm91cCgpICU+JSBncm91cF9ieSh5ZWFyKSAlPiUgc2xpY2VfbWF4KHB1bnRvc190b3RhbGVzLCBuPTEpICU+JSBzZWxlY3QobmFtZSwgZHJpdmVyUmVmKSAlPiUgZ3JvdXBfYnkobmFtZSwgZHJpdmVyUmVmKSAlPiUgbXV0YXRlKHRvdGFsX2NhbXAgPSBzdW0oIE5OID0gbigpKSkgJT4lIGFycmFuZ2UobmFtZSkgDQoNCg0KDQoNCiNsaWJyYXJ5KHRyZWVtYXApDQojbGlicmFyeShkM3RyZWVSKQ0KDQoNCiMgYmFzaWMgdHJlZW1hcA0KI2dnX2VzY19jYW1wZW9uZXMgPC0gdHJlZW1hcChjYW1wZW9uZXNfZXNjLA0KICAgICAgICAgICAgI2luZGV4PWMoIm5hbWUiLCJkcml2ZXJSZWYiKSwNCiAgICAgICAgICAgICN2U2l6ZT0idG90YWxfY2FtcCIsDQogICAgICAgICAgICAjdHlwZT0iaW5kZXgiLA0KICAgICAgICAgICAgI3ZDb2xvciA9ICJuYW1lIiwNCiAgICAgICAgICAgICNmb250c2l6ZS5sYWJlbHM9YygyNSwxNyksDQogICAgICAgICAgICAjYmcubGFiZWxzPWMoInRyYW5zcGFyZW50IiksDQogICAgICAgICAgICAjcGFsZXR0ZSA9ICJTZXQyIiwNCiAgICAgICAgICAgICNhbGlnbi5sYWJlbHM9bGlzdCgNCiAgICAgICAgICAgICAgI2MoImNlbnRlciIsICJjZW50ZXIiKSwgDQogICAgICAgICAgICAgICNjKCJjZW50ZXIiLCAiYm90dG9tIikpLA0KICAgICAgICAgICAgI3RpdGxlID0gIkVzY3VkZXLDrWFzIGNvbiBtw6FzIGNhbXBlb25lcyIsDQogICAgICAgICAgICAjdGl0bGUubGVnZW5kID0gIkVzY3VkZXLDrWFzIikgICANCg0KYGBgDQoNCmBgYHtyLCBmaWcuYWxpZ249J2NlbnRlcid9DQoNCmludGVyX2NhbXAgPC0gZDN0cmVlMihnZ19lc2NfY2FtcGVvbmVzICwgIHJvb3RuYW1lID0gIkVzY3VkZXLDrWFzIHkgQ2FtcGVvbmVzIikNCmludGVyX2NhbXANCg0KDQpgYGANCg0KDQojIyMjIEVuIHZhbG9yZXMgYWJzb2x1dG9zDQoNCmBgYHtyfQ0KY2FtcGVvbmVzX2VzYyA8LSBmdWxsX2pvaW4ocGlsb3RvcywgcmVzdWx0YWRvcywgYygiZHJpdmVySWQiID0gImRyaXZlcklkIikpICU+JSBmdWxsX2pvaW4oLiwgY2FycmVyYXMsIGMoInJhY2VJZCIgPSAicmFjZUlkIikpICU+JSBzZWxlY3QoZHJpdmVySWQsIGRyaXZlclJlZiwgbmF0aW9uYWxpdHksIGNvbnN0cnVjdG9ySWQsIHBvaW50cywgeWVhciwgcm91bmQpICU+JSBmdWxsX2pvaW4oLiwgZXNjdWRlcmlhcywgYygiY29uc3RydWN0b3JJZCIgPSAiY29uc3RydWN0b3JJZCIpKSAlPiUgc2VsZWN0KGRyaXZlcklkLCBkcml2ZXJSZWYsIG5hdGlvbmFsaXR5LngsIGNvbnN0cnVjdG9ySWQsIHBvaW50cywgeWVhciwgbmFtZSwgcm91bmQpICU+JSAgZ3JvdXBfYnkoeWVhciwgZHJpdmVyUmVmKSAlPiUgIG11dGF0ZShwdW50b3NfdG90YWxlcyA9IGN1bXN1bShwb2ludHMpKSAlPiUgdW5ncm91cCgpICU+JSBncm91cF9ieSh5ZWFyKSAlPiUgc2xpY2VfbWF4KHB1bnRvc190b3RhbGVzLCBuPTEpICU+JSB1bmdyb3VwKCkgJT4lIGNvdW50KG5hbWUpICU+JSBhcnJhbmdlKGRlc2MobikpDQoNCmNhbXBlb25lc19lc2Mkbj1hcy5mYWN0b3IoY2FtcGVvbmVzX2VzYyRuKQ0KDQpnZ19jYW1wZW9uZXNfZXMgPC0gZ2dwbG90KGNhbXBlb25lc19lc2MsIGFlcyh4PW5hbWUsIHk9bikpICsNCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCB3aWR0aD0yLCBjb2xvcj0id2hpdGUiKSArIA0KICB0aGVtZShheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyYXkxMyIpLA0KICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyYXkxMyIpLA0KICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyYXkxMyIpLA0KICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImdyYXkxMyIpLA0KICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIkJvb2ttYW4iLA0KICAgICAgICBzaXplID0gOCwgZmFjZSA9ICJib2xkIiksIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiLA0KICAgICAgICBjb2xvdXIgPSAiY3lhbiIpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAiZ3JheTEzIiksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoY29sb3VyID0gImdyYXkxMyIpLA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIkJvb2ttYW4iLA0KICAgICAgICBzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIsIGNvbG91ciA9ICJjeWFuIiwgaGp1c3Q9MC41KSwNCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOSwNCiAgICAgICAgZmFjZSA9ICJib2xkIiwgY29sb3VyID0gImN5YW4iKSwNCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgsDQogICAgICAgIGZhY2UgPSAiYm9sZCIsIGNvbG91ciA9ICJncmF5MTMiKSwNCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTEzIiwNCiAgICAgICAgY29sb3VyID0gImdyYXkxMyIsIGxpbmV0eXBlID0gInNvbGlkIiksDQogICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTEzIiwNCiAgICAgICAgY29sb3VyID0gImdyYXkxMyIsIGxpbmV0eXBlID0gInNvbGlkIiksDQogICAgbGVnZW5kLmtleSA9IGVsZW1lbnRfcmVjdChmaWxsID0gImN5YW4iKSwNCiAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXkxMyIpKSArbGFicyh0aXRsZSA9ICJDQU1QRU9OQVRPUyBQT1IgRVNDVURFUklBIiwNCiAgICB4ID0gTlVMTCwgeSA9IE5VTEwpDQoNCg0KZ2dwbG90bHkoZ2dfY2FtcGVvbmVzX2VzKQ0KDQpgYGANCg0KDQogIA0KIyMjIE11bmRpYWxlcyBwb3IgcGlsb3RvcyB5IG5hY2lvbmFsaWRhZCAgDQoNCmBgYHtyLCBldmFsID0gVFJVRSwgZWNobyA9IFRSVUV9DQoNCg0KaWQgPC0gcm93bmFtZXMoY2FtcGVvbmVzKQ0KY2FtcGVvbmVzIDwtIGNiaW5kKGlkPWlkLCBjYW1wZW9uZXMpDQpjYW1wZW9uZXNbLCBjKDEpXSA8LSBzYXBwbHkoY2FtcGVvbmVzWywgYygxKV0sIGFzLm51bWVyaWMpDQoNCmxhYmVsX2NhbXBlb25lcyA8LSBjYW1wZW9uZXMNCm51bWJlcl9vZl9iYXIgPC0gbnJvdyhsYWJlbF9jYW1wZW9uZXMpDQoNCmFuZ2xlIDwtIDkwIC0gMzYwICogKGxhYmVsX2NhbXBlb25lcyRpZC0wLjUpIC9udW1iZXJfb2ZfYmFyICAgIA0KbGFiZWxfY2FtcGVvbmVzJGhqdXN0IDwtIGlmZWxzZSggYW5nbGUgPCAtOTAsIDEsIDApDQpsYWJlbF9jYW1wZW9uZXMkYW5nbGUgPC0gaWZlbHNlKGFuZ2xlIDwgLTkwLCBhbmdsZSsxODAsIGFuZ2xlKQ0KDQpiYXNlX2NhbXBlb25lcyA8LSBjYW1wZW9uZXMgJT4lIA0KICBncm91cF9ieShuYXRpb25hbGl0eS54KSAlPiUgDQogIHN1bW1hcmlzZShzdGFydD1taW4oaWQpLCBlbmQ9bWF4KGlkKSkgJT4lIA0KICByb3d3aXNlKCkgJT4lIA0KICBtdXRhdGUodGl0bGU9bWVhbihjKHN0YXJ0LCBlbmQpKSkNCg0KZ3JpZF9jYW1wZW9uZXMgPC0gYmFzZV9jYW1wZW9uZXMNCmdyaWRfY2FtcGVvbmVzJGVuZCA8LSBncmlkX2NhbXBlb25lcyRlbmRbIGMoIG5yb3coZ3JpZF9jYW1wZW9uZXMpLCAxOm5yb3coZ3JpZF9jYW1wZW9uZXMpLTEpXSArIDENCmdyaWRfY2FtcGVvbmVzJHN0YXJ0IDwtIGdyaWRfY2FtcGVvbmVzJHN0YXJ0IC0gMQ0KZ3JpZF9jYW1wZW9uZXMgPC0gZ3JpZF9jYW1wZW9uZXNbLTEsXQ0KDQpnZ19jaXJjX3ZpY3RvcmlhcyA8LSBnZ3Bsb3QoY2FtcGVvbmVzLCBhZXMoeD1hcy5mYWN0b3IoeWVhciksIHk9dG90YWxfY2FtcGVvbmF0b3MsIGZpbGw9bmF0aW9uYWxpdHkueCwgY29sb3IgPSBuYXRpb25hbGl0eS54KSkgKyBnZW9tX2JhcihhZXMoeD1hcy5mYWN0b3IoaWQpLCB5PXRvdGFsX2NhbXBlb25hdG9zLCBmaWxsPW5hdGlvbmFsaXR5LngpLCBzdGF0PSJpZGVudGl0eSIsIGFscGhhPTAuNSkgKw0KICANCiAgZ2VvbV9zZWdtZW50KGRhdGE9Z3JpZF9jYW1wZW9uZXMsIGFlcyh4ID0gMCwgeSA9IDgsIHhlbmQgPSAzMiwgeWVuZCA9IDgpLCBjb2xvdXIgPSAiZ3JleSIsIGFscGhhPTEsIHNpemU9MC4zICwgaW5oZXJpdC5hZXMgPSBGQUxTRSApICsNCiAgZ2VvbV9zZWdtZW50KGRhdGE9Z3JpZF9jYW1wZW9uZXMsIGFlcyh4ID0gMCwgeSA9IDYsIHhlbmQgPSAzMiwgeWVuZCA9IDYpLCBjb2xvdXIgPSAiZ3JleSIsIGFscGhhPTEsIHNpemU9MC4zICwgaW5oZXJpdC5hZXMgPSBGQUxTRSApICsNCiAgZ2VvbV9zZWdtZW50KGRhdGE9Z3JpZF9jYW1wZW9uZXMsIGFlcyh4ID0gMCwgeSA9IDQsIHhlbmQgPSAzMiwgeWVuZCA9IDQpLCBjb2xvdXIgPSAiZ3JleSIsIGFscGhhPTEsIHNpemU9MC4zICwgaW5oZXJpdC5hZXMgPSBGQUxTRSApICsNCiAgZ2VvbV9zZWdtZW50KGRhdGE9Z3JpZF9jYW1wZW9uZXMsIGFlcyh4ID0gMCwgeSA9IDIsIHhlbmQgPSAzMiwgeWVuZCA9IDIpLCBjb2xvdXIgPSAiZ3JleSIsIGFscGhhPTEsIHNpemU9MC4zICwgaW5oZXJpdC5hZXMgPSBGQUxTRSApICsNCiAgDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IHJlcChtYXgoY2FtcGVvbmVzJGlkKSw0KSwgeSA9IGMoMiwgNCwgNiwgOCksIGxhYmVsID0gYygiMiIsICI0IiwgIjYiLCAiOCIpICwgY29sb3I9IndoaXRlIiwgc2l6ZT0zICwgYW5nbGU9MCwgZm9udGZhY2U9ImJvbGQiLCBoanVzdD0xKSArDQogIA0KICAgZ2VvbV9iYXIoYWVzKHg9YXMuZmFjdG9yKGlkKSwgeT10b3RhbF9jYW1wZW9uYXRvcywgZmlsbD1uYXRpb25hbGl0eS54KSwgc3RhdD0iaWRlbnRpdHkiLCBhbHBoYT0wLjUpICsNCiAgeWxpbSgtMTAsMjEpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoDQogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLA0KICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgcGxvdC5tYXJnaW4gPSB1bml0KHJlcCgtMSw0KSwgImNtIikgKSArDQogIGNvb3JkX3BvbGFyKCkgKyANCiAgZ2VvbV90ZXh0KGRhdGE9bGFiZWxfY2FtcGVvbmVzLCBhZXMoeD1pZCwgeT0xMCwgbGFiZWw9ZHJpdmVyUmVmLCBoanVzdD1oanVzdCksIGNvbG9yPSJ3aGl0ZSIsIGZvbnRmYWNlPSJib2xkIixhbHBoYT0wLjYsIHNpemU9My41LCBhbmdsZT0gbGFiZWxfY2FtcGVvbmVzJGFuZ2xlLCBpbmhlcml0LmFlcyA9IEZBTFNFICkgKw0KDQogIGdlb21fc2VnbWVudChkYXRhPWdyaWRfY2FtcGVvbmVzLCBhZXMoeCA9IDAuNzAsIHkgPSAtMSwgeGVuZCA9IDIuNDUsIHllbmQgPSAtMSksIGNvbG91ciA9ICJ3aGl0ZSIsIGFscGhhPTEsIHNpemU9MC4zICwgaW5oZXJpdC5hZXMgPSBGQUxTRSApICArDQogIGdlb21fc2VnbWVudChkYXRhPWdyaWRfY2FtcGVvbmVzLCBhZXMoeCA9IDIuNiwgeSA9IC0xLCB4ZW5kID0gMy41NSwgeWVuZCA9IC0xKSwgY29sb3VyID0gIndoaXRlIiwgYWxwaGE9MSwgc2l6ZT0wLjMgLCBpbmhlcml0LmFlcyA9IEZBTFNFICkgKw0KICBnZW9tX3NlZ21lbnQoZGF0YT1ncmlkX2NhbXBlb25lcywgYWVzKHggPSAzLjY1LCB5ID0gLTEsIHhlbmQgPSA1LjQ1LCB5ZW5kID0gLTEpLCBjb2xvdXIgPSAid2hpdGUiLCBhbHBoYT0xLCBzaXplPTAuMyAsIGluaGVyaXQuYWVzID0gRkFMU0UgKSArDQogIGdlb21fc2VnbWVudChkYXRhPWdyaWRfY2FtcGVvbmVzLCBhZXMoeCA9IDUuNTUsIHkgPSAtMSwgeGVuZCA9IDcuMzUsIHllbmQgPSAtMSksIGNvbG91ciA9ICJ3aGl0ZSIsIGFscGhhPTEsIHNpemU9MC4zICwgaW5oZXJpdC5hZXMgPSBGQUxTRSApICsNCiAgZ2VvbV9zZWdtZW50KGRhdGE9Z3JpZF9jYW1wZW9uZXMsIGFlcyh4ID0gNy41LCB5ID0gLTEsIHhlbmQgPSAxMC41MCwgeWVuZCA9IC0xKSwgY29sb3VyID0gIndoaXRlIiwgYWxwaGE9MSwgc2l6ZT0wLjMgLCBpbmhlcml0LmFlcyA9IEZBTFNFICkgKw0KICBnZW9tX3NlZ21lbnQoZGF0YT1ncmlkX2NhbXBlb25lcywgYWVzKHggPSAxMC43LCB5ID0gLTEsIHhlbmQgPSAxOS4yMCwgeWVuZCA9IC0xKSwgY29sb3VyID0gIndoaXRlIiwgYWxwaGE9MSwgc2l6ZT0wLjMgLCBpbmhlcml0LmFlcyA9IEZBTFNFICkgKw0KICBnZW9tX3NlZ21lbnQoZGF0YT1ncmlkX2NhbXBlb25lcywgYWVzKHggPSAxOS40LCB5ID0gLTEsIHhlbmQgPSAyMC4zLCB5ZW5kID0gLTEpLCBjb2xvdXIgPSAid2hpdGUiLCBhbHBoYT0xLCBzaXplPTAuMyAsIGluaGVyaXQuYWVzID0gRkFMU0UgKSArDQogIGdlb21fc2VnbWVudChkYXRhPWdyaWRfY2FtcGVvbmVzLCBhZXMoeCA9IDIwLjQ1LCB5ID0gLTEsIHhlbmQgPSAyMy40LCB5ZW5kID0gLTEpLCBjb2xvdXIgPSAid2hpdGUiLCBhbHBoYT0xLCBzaXplPTAuMyAsIGluaGVyaXQuYWVzID0gRkFMU0UgKSArIA0KICBnZW9tX3NlZ21lbnQoZGF0YT1ncmlkX2NhbXBlb25lcywgYWVzKHggPSAyMy42NSwgeSA9IC0xLCB4ZW5kID0gMjQuMzUsIHllbmQgPSAtMSksIGNvbG91ciA9ICJ3aGl0ZSIsIGFscGhhPTEsIHNpemU9MC4zICwgaW5oZXJpdC5hZXMgPSBGQUxTRSApICsgDQogIGdlb21fc2VnbWVudChkYXRhPWdyaWRfY2FtcGVvbmVzLCBhZXMoeCA9IDI0LjYwLCB5ID0gLTEsIHhlbmQgPSAyNywgeWVuZCA9IC0xKSwgY29sb3VyID0gIndoaXRlIiwgYWxwaGE9MSwgc2l6ZT0wLjMgLCBpbmhlcml0LmFlcyA9IEZBTFNFICkgKw0KICBnZW9tX3NlZ21lbnQoZGF0YT1ncmlkX2NhbXBlb25lcywgYWVzKHggPSAyNy4yLCB5ID0gLTEsIHhlbmQgPSAyOS41LCB5ZW5kID0gLTEpLCBjb2xvdXIgPSAid2hpdGUiLCBhbHBoYT0xLCBzaXplPTAuMyAsIGluaGVyaXQuYWVzID0gRkFMU0UgKSArDQogIGdlb21fc2VnbWVudChkYXRhPWdyaWRfY2FtcGVvbmVzLCBhZXMoeCA9IDI5LjcsIHkgPSAtMSwgeGVuZCA9IDMwLjUsIHllbmQgPSAtMSksIGNvbG91ciA9ICJ3aGl0ZSIsIGFscGhhPTEsIHNpemU9MC4zICwgaW5oZXJpdC5hZXMgPSBGQUxTRSApICsgDQogIGdlb21fc2VnbWVudChkYXRhPWdyaWRfY2FtcGVvbmVzLCBhZXMoeCA9IDMwLjcsIHkgPSAtMSwgeGVuZCA9IDMxLjUsIHllbmQgPSAtMSksIGNvbG91ciA9ICJ3aGl0ZSIsIGFscGhhPTEsIHNpemU9MC4zICwgaW5oZXJpdC5hZXMgPSBGQUxTRSApICsNCiAgZ2VvbV9zZWdtZW50KGRhdGE9Z3JpZF9jYW1wZW9uZXMsIGFlcyh4ID0gMzEuNywgeSA9IC0xLCB4ZW5kID0gMzIuNSwgeWVuZCA9IC0xKSwgY29sb3VyID0gIndoaXRlIiwgYWxwaGE9MSwgc2l6ZT0wLjMgLCBpbmhlcml0LmFlcyA9IEZBTFNFICkgKw0KICBnZW9tX3NlZ21lbnQoZGF0YT1ncmlkX2NhbXBlb25lcywgYWVzKHggPSAzMi43LCB5ID0gLTEsIHhlbmQgPSAzMy41LCB5ZW5kID0gLTEpLCBjb2xvdXIgPSAid2hpdGUiLCBhbHBoYT0xLCBzaXplPTAuMyAsIGluaGVyaXQuYWVzID0gRkFMU0UgKSArIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJ3aGl0ZSIpLA0KICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dCggY29sb3VyID0gIndoaXRlIiksIA0KICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXkxMyIsIGNvbG91ciA9ICJncmF5MTMiKSwNCiAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTEzIiksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwNCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTEzIiAsIGNvbG91ciA9ICJncmF5MTMiKSwNCiAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiICwgY29sb3VyID0gImdyYXkxMyIpKStsYWJzKGNvbG91ciA9ICJOYWNpb25hbGlkYWQiLCBmaWxsID0gIk5hY2lvbmFsaWRhZCIpDQojZ2dfY2lyY192aWN0b3JpYXMNCiNsYXMgc2lndWllbnRlcyBsaW5lYXMgZGUgY29kaWdvIHNlIHV0aWxpemFuIHBhcmEgZWxpbWluYXIgbG9zIGJvcmRlcyBibGFuY29zDQpnZ3NhdmUoIi4vcGxvdHMvZ2dfY2lyY192aWN0b3JpYXMucG5nIiwgd2lkdGggPSA4LCBoZWlnaHQgPSA1KQ0KYGBgDQoNCjxjZW50ZXI+DQoNCg0KIVtDYW1wZW9uZXMgZGVsIG11bmRvXSguL3Bsb3RzL2dnX2NpcmNfdmljdG9yaWFzLnBuZyl7d2lkdGg9ODAwIGhlaWdodD02MDB9DQoNCg0KPC9jZW50ZXI+DQoNCg0KIyMgMy4zIFRlbXBvcmFkYSAyMDIxDQoNCiMjIyBDYW1wZcOzbiBkZWwgbXVuZG97LnRhYnNldH0NCg0KIyMjIyBWZXJzdGFwcGVuDQoNCjxjZW50ZXI+DQohW1ZlcnN0YXBwZW4gLSBOdWV2byBDYW1wZcOzbiAyMDIxXSguL2ltYWdlbmVzL0NBTVBFT04vY2FtcGVvbl92ZXJzdGFwcGVuLmpwZyl7d2lkdGg9NjQwIGhlaWdodD04MDB9DQo8L2NlbnRlcj4NCg0KIyMjIyBGaW5hbCBkZSBpbmZhcnRvDQoNCmBgYHtyfQ0KDQpzYWxpZGEgPC0gaW1hZ2VfcmVhZCgiLi9pbWFnZW5lcy9DQU1QRU9OL2hhbWlsdG9uX2FkZWwuanBnIikgJT4lIGltYWdlX3NjYWxlKC4sICI1MDAiKSU+JSAgaW1hZ2VfYW5ub3RhdGUoLiwgIkhhbWlsdG9uIHNlIHBvbmUgcG9yIGRlbGFudGUiLCBzaXplID0gMjAsIGdyYXZpdHkgPSAibm9ydGh3ZXN0IiwgY29sb3IgPSAiY3lhbiIsIGJveGNvbG9yID0gImdyYXkxMyIpDQpsYXRpZmkgPC0gaW1hZ2VfcmVhZCgiLi9pbWFnZW5lcy9DQU1QRU9OL2xhdGlmaS5qcGciKSAlPiUgaW1hZ2Vfc2NhbGUoLiwgIjUwMCIpJT4lICBpbWFnZV9hbm5vdGF0ZSguLCAiQWNjaWRlbnRlIGRlIExhdGlmaSIsIHNpemUgPSA0MCwgZ3Jhdml0eSA9ICJub3J0aHdlc3QiLCBjb2xvciA9ICJjeWFuIiwgYm94Y29sb3IgPSAiZ3JheTEzIikNCnNhZmV0eSA8LSBpbWFnZV9yZWFkKCIuL2ltYWdlbmVzL0NBTVBFT04vc2FmZXR5LmpwZyIpICU+JSBpbWFnZV9zY2FsZSguLCAiNTAwIiklPiUgIGltYWdlX2Fubm90YXRlKC4sICJTYWxlIGVsIHNhZmV0eSBjYXIiLCBzaXplID0gNDAsIGdyYXZpdHkgPSAibm9ydGh3ZXN0IiwgY29sb3IgPSAiY3lhbiIsIGJveGNvbG9yID0gImdyYXkxMyIpDQpydWVkYV9hX3J1ZWRhIDwtIGltYWdlX3JlYWQoIi4vaW1hZ2VuZXMvQ0FNUEVPTi9ydWVkYWFydWVkYS5qcGVnIikgJT4lIGltYWdlX3NjYWxlKC4sICI1MDAiKSU+JSAgaW1hZ2VfYW5ub3RhdGUoLiwgIklndWFsZGFkIG3DoXhpbWEiLCBzaXplID0gMzAsIGdyYXZpdHkgPSAibm9ydGh3ZXN0IiwgY29sb3IgPSAiY3lhbiIsIGJveGNvbG9yID0gImdyYXkxMyIpDQptZXRhIDwtIGltYWdlX3JlYWQoIi4vaW1hZ2VuZXMvQ0FNUEVPTi92ZXJzdGFwcGVuX2dhbmEuanBnIikgJT4lIGltYWdlX3NjYWxlKC4sICI1MDAiKSU+JSAgaW1hZ2VfYW5ub3RhdGUoLiwgIlZlcnN0YXBwZW4gc2UgaGFjZSBjb24gbGEgdmljdG9yaWEiLCBzaXplID0gMjAsIGdyYXZpdHkgPSAibm9ydGh3ZXN0IiwgY29sb3IgPSAiY3lhbiIsIGJveGNvbG9yID0gImdyYXkxMyIpDQp0cm9mZW8gPC0gaW1hZ2VfcmVhZCgiLi9pbWFnZW5lcy9DQU1QRU9OL2NhbXBlb25fdHJvZmVvLmpwZyIpICU+JSBpbWFnZV9zY2FsZSguLCAiNTAwIiklPiUgIGltYWdlX2Fubm90YXRlKC4sICJOdWV2byBjYW1wZcOzbiBkZWwgbXVuZG8iLCBzaXplID0gMzAsIGdyYXZpdHkgPSAibm9ydGh3ZXN0IiwgY29sb3IgPSAiY3lhbiIsIGJveGNvbG9yID0gImdyYXkxMyIpDQpsYXN0X3JhY2UgPC0gYyhzYWxpZGEsIGxhdGlmaSwgc2FmZXR5LCBydWVkYV9hX3J1ZWRhLCBtZXRhLCB0cm9mZW8pDQoNCmltYWdlX2FuaW1hdGUoaW1hZ2Vfc2NhbGUobGFzdF9yYWNlKSwgZnBzID0gMC41KQ0KYGBgDQoNCiMjIyMgVmVyc3RhcHBlbiB2cyBIYW1pbHRvbg0KDQpgYGB7cn0NCnZlcnNfdnNfaGFtIDwtIGRhdGEuZnJhbWUoDQogICJub21icmUiID0gYygiTWF4IFZlcnN0YXBwZW4iLCAiTGV3aXMgSGFtaWx0b24iKSwNCiAgInBpbG90byIgPSBjKCIuL2ltYWdlbmVzL3BpbG90b3MvdmVyc3RhcHBlbi5qcGciLCIuL2ltYWdlbmVzL3BpbG90b3MvaGFtaWx0b24ucG5nIiksDQogICJwYWlzIiA9IGMoIi4vaW1hZ2VuZXMvcGFpc2VzL2hvbGFuZGEucG5nIiwgIi4vaW1hZ2VuZXMvcGFpc2VzL3VrLnBuZyIpLA0KICAiZXNjdWRlcmlhIiA9IGMoIi4vaW1hZ2VuZXMvZXNjdWRlcmlhcy9yZWRidWxsLnBuZyIsICIuL2ltYWdlbmVzL2VzY3VkZXJpYXMvbWVyY2VkZXMucG5nIiksDQogICJwdW50b3MiID0gYygzOTUuNSwgMzg3LjUpLA0KICAidmljdG9yaWFzIiA9IGMoMTAsIDgpLA0KICAicG9kaXVtcyIgPSBjKDE4LCAxNyksDQogICJwb2xlcyIgPSBjKDEwLCA1KSwNCiAgInZ1ZWx0YXNfcmFwaWRhcyIgPSBjKDYsIDYpKQ0KICANCg0KIA0KdGFibGFfdmVyX2hhbSA8LSB2ZXJzX3ZzX2hhbSAlPiUgZ3QoKSAlPiUgDQogIHRleHRfdHJhbnNmb3JtKCBsb2NhdGlvbnMgPSBjZWxsc19ib2R5KGNvbHVtbnMgPSBjKHBpbG90bykpLCBmbiA9IGZ1bmN0aW9uKHgpIHtndDo6bG9jYWxfaW1hZ2UoeCwgaGVpZ2h0ID0gODApfSkgJT4lIA0KICB0ZXh0X3RyYW5zZm9ybSggbG9jYXRpb25zID0gY2VsbHNfYm9keShjb2x1bW5zID0gYyhwYWlzKSksIGZuID0gZnVuY3Rpb24oeCkge2d0Ojpsb2NhbF9pbWFnZSh4LCBoZWlnaHQgPSA2MCl9KSAlPiUgIA0KICB0ZXh0X3RyYW5zZm9ybSggbG9jYXRpb25zID0gY2VsbHNfYm9keShjb2x1bW5zID0gYyhlc2N1ZGVyaWEpKSwgZm4gPSBmdW5jdGlvbih4KSB7Z3Q6OmxvY2FsX2ltYWdlKHgsIGhlaWdodCA9IDgwKX0pICU+JSANCiAgdGFiX2hlYWRlcih0aXRsZSA9IG1kKCIqKlZlcnN0YXBwZW4gdnMgSGFtaWx0b24qKiIpLCBzdWJ0aXRsZSA9IG1kKCIyMDIxIikpICU+JSAgIGNvbHNfbGFiZWwoDQogICAgbm9tYnJlID0gaHRtbCgiIiksDQogICAgcGlsb3RvID0gaHRtbCgiIiksDQogICAgcGFpcyA9IGh0bWwoIiIpLA0KICAgIGVzY3VkZXJpYSA9IGh0bWwoIkVzY3VkZXLDrWEiKSwNCiAgICBwdW50b3MgPSBodG1sKCJQdW50b3MiKSwNCiAgICB2aWN0b3JpYXMgPSBodG1sKCJWaWN0b3JpYXMiKSwNCiAgICBwb2RpdW1zID0gaHRtbCgiUG9kaXVtcyIpLA0KICAgIHBvbGVzID0gaHRtbCgiUG9sZXMiKSwNCiAgICB2dWVsdGFzX3JhcGlkYXMgPSBodG1sKCJWdWVsdGFzIHLDoXBpZGFzIikpICU+JSAgDQogIHRhYl9vcHRpb25zKHRhYmxlLmJhY2tncm91bmQuY29sb3IgPSAiZ3JheTEzIiwgICB0YWJsZS5mb250LmNvbG9yLmxpZ2h0ID0gImN5YW4iKSAlPiUgDQogIGNvbHNfYWxpZ24oYWxpZ24gPSAiY2VudGVyIiwNCiAgY29sdW1ucyA9IGV2ZXJ5dGhpbmcoKSkNCg0KDQp0YWJsYV92ZXJfaGFtDQpgYGANCg0KDQojIyMgUGFycmlsbGEgZGUgcGlsb3RvcyANCg0KYGBge3J9DQoNCnBpbG90b3NfMjAyMSA8LSBmdWxsX2pvaW4oY2FycmVyYXMsIHJlc3VsdGFkb3MsIGMoInJhY2VJZCIgPSAicmFjZUlkIikgKSAlPiUgDQogIGZ1bGxfam9pbiguLHBpbG90b3MsIGMoImRyaXZlcklkIj0iZHJpdmVySWQiKSkgJT4lIA0KICBmaWx0ZXIoeWVhcj09IjIwMjEiKSAlPiUgDQogIHNlbGVjdChmb3JlbmFtZSxzdXJuYW1lLCB5ZWFyKSAlPiUgZGlzdGluY3QoZm9yZW5hbWUsc3VybmFtZSkgJT4lIG5hLm9taXQoKSAlPiUgYXJyYW5nZShzdXJuYW1lKSAlPiUgc3RyX3JlcGxhY2VfYWxsKC4sICLDg8KpIiwgIsOpIikgJT4lIHN0cl9yZXBsYWNlX2FsbCguLCAiw4PCpCIsICLDpCIpICU+JSBzdHJfcmVwbGFjZV9hbGwoLiwgIsODwrYiLCAiw7YiKQ0KDQpub21icmVzX25vcm1hbGVzIDwtIGMoIkFsb25zbyIsICJCb3R0YXMiLCAiR2FzbHkiLCAiR2lvdmluYXp6aSIsICJIYW1pbHRvbiIsICJMYXRpZmkiLCAiTGVjbGVyYyIsICJNYXplcGluIiwgIk5vcnJpcyIsICJPY29uIiwgIlDDqXJleiIsICJSw6Rpa2vDtm5lbiIsICJSaWNjaWFyZG8iLCAiUnVzc2VsbCIsICJTYWlueiIsICJTY2h1bWFjaGVyIiwgIlN0cm9sbCIsICJUc3Vub2RhIiwgIlZlcnN0YXBwZW4iLCAiVmV0dGVsIikNCg0KcGlsb3Rvc18yMDIxIDwtICBmdWxsX2pvaW4oY2FycmVyYXMsIHJlc3VsdGFkb3MsIGMoInJhY2VJZCIgPSAicmFjZUlkIikgKSAlPiUgDQogIGZ1bGxfam9pbiguLHBpbG90b3MsIGMoImRyaXZlcklkIj0iZHJpdmVySWQiKSkgJT4lIA0KICBmaWx0ZXIoeWVhcj09IjIwMjEiKSAlPiUgDQogIHNlbGVjdChmb3JlbmFtZSxzdXJuYW1lLCB5ZWFyKSAlPiUgZGlzdGluY3QoZm9yZW5hbWUsc3VybmFtZSkgJT4lIG5hLm9taXQoKSAlPiUgYXJyYW5nZShzdXJuYW1lKSAlPiUgYWRkX2NvbHVtbihub21icmVzX25vcm1hbGVzKSAgDQogDQoNCiMgUMODwqlyZXoNCiMgUsODwqRpa2vDg8K2bmVuDQpmb3Rvc19waWxfMjAyMSA8LSBjKCIuL2ltYWdlbmVzL3BpbG90b3MvYWxvbnNvLnBuZyIsICIuL2ltYWdlbmVzL3BpbG90b3MvYm90dGFzLnBuZyIsICIuL2ltYWdlbmVzL3BpbG90b3MvZ2FzbHkucG5nIiwgIi4vaW1hZ2VuZXMvcGlsb3Rvcy9naW92aW5henppLmpwZyIsICIuL2ltYWdlbmVzL3BpbG90b3MvaGFtaWx0b24ucG5nIiwgIi4vaW1hZ2VuZXMvcGlsb3Rvcy9sYXRpZmkucG5nIiwgIi4vaW1hZ2VuZXMvcGlsb3Rvcy9sZWNsZXJjLnBuZyIsICIuL2ltYWdlbmVzL3BpbG90b3MvbWF6ZXBpbi5wbmciLCAiLi9pbWFnZW5lcy9waWxvdG9zL25vcnJpcy5wbmciLCAiLi9pbWFnZW5lcy9waWxvdG9zL29jb24uanBnIiwgIi4vaW1hZ2VuZXMvcGlsb3Rvcy9wZXJlei5wbmciLCAiLi9pbWFnZW5lcy9waWxvdG9zL3JhaWtrb25lbi5wbmciLCAiLi9pbWFnZW5lcy9waWxvdG9zL3JpY2NpYXJkby5wbmciLCAiLi9pbWFnZW5lcy9waWxvdG9zL3J1c3NlbGwucG5nIiwgIi4vaW1hZ2VuZXMvcGlsb3Rvcy9zYWluei5wbmciLCAiLi9pbWFnZW5lcy9waWxvdG9zL21pY2sucG5nIiwgIi4vaW1hZ2VuZXMvcGlsb3Rvcy9zdHJvbGwucG5nIiwgIi4vaW1hZ2VuZXMvcGlsb3Rvcy90c3Vub2RhLnBuZyIsICIuL2ltYWdlbmVzL3BpbG90b3MvdmVyc3RhcHBlbi5qcGciLCAiLi9pbWFnZW5lcy9waWxvdG9zL3ZldHRlbC5wbmciKQ0KDQpmb3Rvc19wYWlzXzIwMjEgPC0gYygiLi9pbWFnZW5lcy9wYWlzZXMvZXNwYW55YS5wbmciLCAiLi9pbWFnZW5lcy9wYWlzZXMvZmlubGFuZGlhLnBuZyIsICIuL2ltYWdlbmVzL3BhaXNlcy9mcmFuY2lhLnBuZyIsICIuL2ltYWdlbmVzL3BhaXNlcy9pdGFsaWEucG5nIiwiLi9pbWFnZW5lcy9wYWlzZXMvdWsucG5nIiwgIi4vaW1hZ2VuZXMvcGFpc2VzL2NhbmFkYS5wbmciLCIuL2ltYWdlbmVzL3BhaXNlcy9tb25hY28ucG5nIiwgIi4vaW1hZ2VuZXMvcGFpc2VzL3J1c2lhLnBuZyIsIi4vaW1hZ2VuZXMvcGFpc2VzL3VrLnBuZyIsICIuL2ltYWdlbmVzL3BhaXNlcy9mcmFuY2lhLnBuZyIsIi4vaW1hZ2VuZXMvcGFpc2VzL21leGljby5wbmciLCAiLi9pbWFnZW5lcy9wYWlzZXMvZmlubGFuZGlhLnBuZyIsIi4vaW1hZ2VuZXMvcGFpc2VzL2F1c3RyYWxpYS5wbmciLCAiLi9pbWFnZW5lcy9wYWlzZXMvdWsucG5nIiwiLi9pbWFnZW5lcy9wYWlzZXMvZXNwYW55YS5wbmciLCAiLi9pbWFnZW5lcy9wYWlzZXMvYWxlbWFuaWEucG5nIiwiLi9pbWFnZW5lcy9wYWlzZXMvY2FuYWRhLnBuZyIsICIuL2ltYWdlbmVzL3BhaXNlcy9qYXBvbi5wbmciLCIuL2ltYWdlbmVzL3BhaXNlcy9ob2xhbmRhLnBuZyIsICIuL2ltYWdlbmVzL3BhaXNlcy9hbGVtYW5pYS5wbmciKQ0KDQpmb3Rvc19lc2NfMjAyMSA8LSBjKCIuL2ltYWdlbmVzL2VzY3VkZXJpYXMvYWxwaW5lLnBuZyIsIi4vaW1hZ2VuZXMvZXNjdWRlcmlhcy9tZXJjZWRlcy5wbmciLCIuL2ltYWdlbmVzL2VzY3VkZXJpYXMvYWxwaGF0YXVyaS5wbmciLCAiLi9pbWFnZW5lcy9lc2N1ZGVyaWFzL2FsZmFyb21lby5qcGciLCIuL2ltYWdlbmVzL2VzY3VkZXJpYXMvbWVyY2VkZXMucG5nIiwgIi4vaW1hZ2VuZXMvZXNjdWRlcmlhcy93aWxsaWFtcy5wbmciLCIuL2ltYWdlbmVzL2VzY3VkZXJpYXMvZmVycmFyaS5wbmciLCAiLi9pbWFnZW5lcy9lc2N1ZGVyaWFzL2hhYXMucG5nIiwiLi9pbWFnZW5lcy9lc2N1ZGVyaWFzL21jbGFyZW4ucG5nIiwgIi4vaW1hZ2VuZXMvZXNjdWRlcmlhcy9hbHBpbmUucG5nIiwiLi9pbWFnZW5lcy9lc2N1ZGVyaWFzL3JlZGJ1bGwucG5nIiwgIi4vaW1hZ2VuZXMvZXNjdWRlcmlhcy9hbGZhcm9tZW8uanBnIiwiLi9pbWFnZW5lcy9lc2N1ZGVyaWFzL21jbGFyZW4ucG5nIiwgIi4vaW1hZ2VuZXMvZXNjdWRlcmlhcy93aWxsaWFtcy5wbmciLCIuL2ltYWdlbmVzL2VzY3VkZXJpYXMvZmVycmFyaS5wbmciLCAiLi9pbWFnZW5lcy9lc2N1ZGVyaWFzL2hhYXMucG5nIiwiLi9pbWFnZW5lcy9lc2N1ZGVyaWFzL2FzdG9uLnBuZyIsICIuL2ltYWdlbmVzL2VzY3VkZXJpYXMvYWxwaGF0YXVyaS5wbmciLCIuL2ltYWdlbmVzL2VzY3VkZXJpYXMvcmVkYnVsbC5wbmciLCAiLi9pbWFnZW5lcy9lc2N1ZGVyaWFzL2FzdG9uLnBuZyIpDQoNCnBpbG90b3NfMjAyMSA8LSBwaWxvdG9zXzIwMjEgJT4lDQogIGFkZF9jb2x1bW4oZm90b3NfcGlsXzIwMjEsIGZvdG9zX3BhaXNfMjAyMSwgZm90b3NfZXNjXzIwMjEpICU+JSBzZWxlY3Qobm9tYnJlc19ub3JtYWxlcywgZm90b3NfcGlsXzIwMjEsIGZvdG9zX3BhaXNfMjAyMSwgZm90b3NfZXNjXzIwMjEpDQoNCg0KbXVuZGlhbF8yMDIxIDwtIHBpbG90b3NfMjAyMSAlPiUgZ3QoKSAlPiUgdGV4dF90cmFuc2Zvcm0oIGxvY2F0aW9ucyA9IGNlbGxzX2JvZHkoY29sdW1ucyA9IGMoZm90b3NfcGlsXzIwMjEpKSwgZm4gPSBmdW5jdGlvbih4KSB7Z3Q6OmxvY2FsX2ltYWdlKHgsIGhlaWdodCA9IDEwMCl9KSAlPiUgdGV4dF90cmFuc2Zvcm0oIGxvY2F0aW9ucyA9IGNlbGxzX2JvZHkoY29sdW1ucyA9IGMoZm90b3NfcGFpc18yMDIxKSksIGZuID0gZnVuY3Rpb24oeCkge2d0Ojpsb2NhbF9pbWFnZSh4LCBoZWlnaHQgPSA1MCl9KSAlPiUgdGV4dF90cmFuc2Zvcm0oIGxvY2F0aW9ucyA9IGNlbGxzX2JvZHkoY29sdW1ucyA9IGMoZm90b3NfZXNjXzIwMjEpKSwgZm4gPSBmdW5jdGlvbih4KSB7Z3Q6OmxvY2FsX2ltYWdlKHgsIGhlaWdodCA9IDcwKX0pICU+JSB0YWJfaGVhZGVyKHRpdGxlID0gbWQoIioqUGlsb3RvcyAyMDIxKioiKSwgc3VidGl0bGUgPSBtZCgiUGFycmlsbGEiKSkgJT4lICAgY29sc19sYWJlbCgNCiAgICBub21icmVzX25vcm1hbGVzID0gaHRtbCgiIiksDQogICAgZm90b3NfcGlsXzIwMjEgPSBodG1sKCIiKSwNCiAgICBmb3Rvc19wYWlzXzIwMjEgPSBodG1sKCIiKSwNCiAgICBmb3Rvc19lc2NfMjAyMSA9IGh0bWwoIiIpKSAlPiUgIA0KICB0YWJfb3B0aW9ucyh0YWJsZS5iYWNrZ3JvdW5kLmNvbG9yID0gImdyYXkxMyIsICAgdGFibGUuZm9udC5jb2xvci5saWdodCA9ICJjeWFuIikgJT4lIA0KICBjb2xzX2FsaWduKGFsaWduID0gImNlbnRlciIsDQogIGNvbHVtbnMgPSBldmVyeXRoaW5nKCkpDQoNCg0KI211bmRpYWxfMjAyMQ0KYGBgDQoNCg0KIyMjIFRlbXBsb3MNCg0KYGBge3IsIGV2YWwgPSBUUlVFLCBlY2hvID0gVFJVRX0NCg0KZ2xvYm9fY2lyYyA8LWNyZWF0ZV9nbG9iZSgpICU+JSBnbG9iZV9wb3YoNDUuNjE1NjAsIDkuMjgxMTEwKSAlPiUgZ2xvYmVfYmFycyhjb29yZHMobGF0LCBsbmcsIGxhYmVsICA9IHZhcmlhYmxlcywgY29sb3IgPSByb3VuZDIpLCBkYXRhID0gY2FycmVyYXNfMjFfdjIpICAlPiUgc2NhbGVfYmFyc19jb2xvcigpDQojZ2xvYm9fY2lyYw0KYGBgDQoNCg0KDQojIyAzLjQgRWwgbmFubw0KDQojIyMgQWxvbnNvIHZzIGNvbXBhw7Flcm9zIGRlIGVxdWlwbw0KDQpgYGB7ciwgZXZhbCA9IFRSVUUsIGVjaG8gPSBUUlVFfQ0KZ2MoKSAjaW5zdHJ1Y2Npb24gcGFyYSBxdWUgY2FyZ3VlIGVsIGdyYWZpY28sIGFsIHNlciB0YW4gY29tcGxlam8gZGEgZXJyb3IgZGUgbm8gc8OpIHF1w6kgcGVybyBjb24gZXN0byBmdW5jaW9uYQ0KZ2dhbG9fdnNfYWxsIDwtIGdncGxvdChkYXRhID0gQUxPX1ZTX0FMTCwgYWVzKHJvdW5kLCBwdW50b3NfYWN1bXVsYWRvcywgY29sb3IgPSBkcml2ZXJSZWYpKSArDQogIGdlb21fbGluZSgpICsNCiAgZ2VvbV9wb2ludCgpICsgDQogIGxhYnModGl0bGUgPSAiQWxvbnNvIGNvbnRyYSBlbCBtdW5kbyIsDQogICAgICAgc3VidGl0bGUgPSAiQWxvbnNvIFZTIGNhZGEgY29tcGHDsWVybyBkZSBlcXVpcG8iLA0KICAgICAgIHkgPSAiUHVudG9zIiwgeCA9ICIiKSArIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JheTMwIiwNCiAgICBsaW5ldHlwZSA9ICJzb2xpZCIpLCBheGlzLnRpY2tzID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmF5MzAiKSwNCiAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJncmF5MjAiKSwNCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9saW5lKGxpbmV0eXBlID0gImJsYW5rIiksDQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUsDQogICAgICAgIGNvbG91ciA9ICJ3aGl0ZSIpLCBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gIndoaXRlIiksDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsDQogICAgICAgIGNvbG91ciA9ICJ3aGl0ZSIsIGhqdXN0ID0gMC41KSwgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gIndoaXRlIiksDQogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJ3aGl0ZSIpLA0KICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiLA0KICAgICAgICBjb2xvdXIgPSAiZ3JheTEzIiwgbGluZXR5cGUgPSAic29saWQiKSwNCiAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmF5MTMiLA0KICAgICAgICBjb2xvdXIgPSAiZ3JheTEzIiwgbGluZXR5cGUgPSAic29saWQiKSwNCiAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiZ3JheTEzIiwNCiAgICAgICAgY29sb3VyID0gImdyYXkxMyIpLCBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyYXkxMyIsDQogICAgICAgIGNvbG91ciA9ICJncmF5MTMiKSkgK2xhYnMoeCA9ICJOwrogY2FycmVyYSIsIGNvbG91ciA9ICJQaWxvdG8iKSArIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLA0KICAgIGhqdXN0ID0gMC41KSkgKyBmYWNldF93cmFwKCB+IHllYXIpICsgdHJhbnNpdGlvbl9yZXZlYWwocm91bmQpDQoNCiNnZ2Fsb192c19hbGwNCg0KYGBgDQoNCiMjIyBBbG9uc28gdnMgSGFtaWx0b24NCmBgYHtyLCBldmFsPVRSVUUsIGVjaG89VFJVRX0NCg0KI3NlIG5lY2VzaXRhIHRlbmVyIGNhcmdhZG8gIm5fY2FycmVyYXNfbm9tIiwgInZpY3Rvcmlhc19jb25fbm9tYnJlIg0KIzEyMzQNCg0KYWxvX3ZzX2hhbV90YWJsYSA8LSBhbG9fdnNfaGFtICU+JSBndCgpICU+JSB0ZXh0X3RyYW5zZm9ybSggbG9jYXRpb25zID0gY2VsbHNfYm9keShjb2x1bW5zID0gYyhmb3Rvc19lc3BfaW5nKSksIGZuID0gZnVuY3Rpb24oeCkge2d0Ojpsb2NhbF9pbWFnZSh4LCBoZWlnaHQgPSA1MCl9KSAlPiUgdGV4dF90cmFuc2Zvcm0oIGxvY2F0aW9ucyA9IGNlbGxzX2JvZHkoY29sdW1ucyA9IGMoZm90b3NfQUxPX3ZzX0hBTSkpLCBmbiA9IGZ1bmN0aW9uKHgpIHtndDo6bG9jYWxfaW1hZ2UoeCwgaGVpZ2h0ID0gMTAwKX0pICU+JSB0YWJfaGVhZGVyKHRpdGxlID0gbWQoIioqQWxvbnNvIHZzIEhhbWlsdG9uKioiKSwgc3VidGl0bGUgPSBtZCgiQ29tcGFyYWNpw7NuIikpICU+JSAgIGNvbHNfbGFiZWwoDQogICAgZHJpdmVyUmVmID0gaHRtbCgiIiksDQogICAgbnVtZXJvX2NhcnJlcmFzID0gaHRtbCgiTsK6IGNhcnJlcmFzIiksDQogICAgbl92aWN0b3JpYXMgPSBodG1sKCJOwrogdmljdG9yaWFzIiksDQogICAgZm90b3NfZXNwX2luZyA9IGh0bWwoIlBhw61zIiksDQogICAgZm90b3NfQUxPX3ZzX0hBTSA9IGh0bWwoIiIpKSAlPiUgIA0KICB0YWJfb3B0aW9ucyh0YWJsZS5iYWNrZ3JvdW5kLmNvbG9yID0gImdyYXkxMyIsICAgdGFibGUuZm9udC5jb2xvci5saWdodCA9ICJjeWFuIikgJT4lIA0KICBjb2xzX2FsaWduKGFsaWduID0gImNlbnRlciIsDQogIGNvbHVtbnMgPSBldmVyeXRoaW5nKCkpDQoNCmFsb192c19oYW1fdGFibGENCmBgYA0KDQoNCg0KDQoNCiMgNC4gVHJhYmFqb3MgZW4gbG9zIHF1ZSB0ZSBoYXMgYmFzYWRvDQpDb24gbG9zIGRhdG9zIHF1ZSBoZW1vcyBlbmNvbnRyYWRvLCBleGlzdGVuIHVuYSBzZXJpZSBkZSBjw7NkaWdvcyBxdWUgeWEgdHJhYmFqYW4gY29uIGVzdG9zIGRhdG9zLCBlc3BlY2lhbG1lbnRlIFtlc3RlXShodHRwczovL3d3dy5rYWdnbGUuY29tL2VrcmVtYmF5YXIvZm9ybXVsYS0xLTcwdGgtYW5uaXZlcnNhcnkpLCBhIHBhcnRpciBkZWwgY3VhbCwgc29icmUgdG9kbywgbm9zIGhlbW9zIGZpamFkbyBlbiBsYSBlc3TDqXRpY2EgZGUgbG9zIGdyw6FmaWNvcyB5IGxhcyBpbWFnZW5lcyBjb24gbGFzIHF1ZSBsb3MgYWNvbXBhw7FhYmEuIFRhbWJpw6luIGhlbW9zIG9idGVuaWRvIGlkZWFzIHBhcmEgdHJhYmFqYXIgbG9zIGRhdG9zLCBwZXJvIGVuIG1lbm9yIG1lZGlkYSBxdWUgZWwgYXBhcnRhZG8gdmlzdWFsLCB5YSBxdWUgZWwgdHJhYmFqbyBjaXRhZG8gc2UgY2VudHJhIHVuaWNhbWVudGUgZW4gbGEgdGVtcG9yYWRhIGFjdHVhbCwgbWllbnRyYXMgcXVlICoqQWx0KyBGb3JtdWxhIDEqKiBjb21iaW5hIHRhbnRvIGxhIGFjdHVhbGlkYWQgY29tbyBsYSBoaXN0b3JpYSBlbiBnZW5lcmFsIGRlIGxhIEYxLg0KDQoNCiMgNS4gQmlibGlvZ3JhZsOtYQ0KDQpMYSBncmFuIHBhcnRlIGRlbCB0cmFiYWpvIHNlIGhhIGNlbnRyYWRvIGVuIGxvcyBkYXRvcyBvYnRlbmlkb3MgYSBwYXJ0aXIgZGUgS2FnZ2xlLCBwb3IgbG8gcXVlIG5vIHNvbiBtdWNoYXMgbGFzIHDDoWdpbmFzIGF1eGlsaWFyZXMgcXVlIGhlbW9zIHV0aWxpemFkby4gIA0KUGFyYSBsYSBvYnRlbmNpw7NuIGRlIGxhcyBhdWRpZW5jaWFzIHNlIGhhbiB1dGlsaXphZG8gdGFudG8gW2VzdGFdKGh0dHBzOi8vd3d3LnRoZWJlc3RmMS5lcy9hbmFsaXNpcy1hc2ktaGFuLWV2b2x1Y2lvbmFkby1sYXMtYXVkaWVuY2lhcy1lbi1lc3BhbmEtZGVzZGUtbGEtMi1hLW1vdmlzdGFyLWYxLykgcMOhZ2luYSB3ZWIgLCBjb21vIFtlc3RlXShodHRwczovL3R3aXR0ZXIuY29tL01lZEYxb3NUVi9zdGF0dXMvMTM3NjQ2MjgzNDg0MjkyMzAwOCkgcG9zdCBkZSB0d2l0dGVyLiANCg0K